// 全局变量
        let canvas = document.getElementById('canvas');
        let connectionSvg = document.getElementById('connectionSvg');
        let nodeIdCounter = 1;
        let selectedNode = null;
        let isDragging = false;
        let dragOffset = { x: 0, y: 0 };
        let isConnecting = false;
        let connectionStart = null;
        let nodes = new Map(); // 存储所有节点
        let connections = new Map(); // 存储所有连接
        let globalParameters = new Map(); // 存储全局参数定义
        let currentFormulaName = null; // 当前编辑的公式名称

        // 端口说明配置
        const portDescriptions = {
            math: {
                add: {
                    inputs: ['第一个加数', '第二个加数', '第三个加数', '第四个加数', '第五个加数', '第六个加数', '第七个加数', '第八个加数', '第九个加数', '第十个加数'],
                    outputs: ['所有数的和']
                },
                subtract: {
                    inputs: ['被减数', '减数'],
                    outputs: ['相减的结果']
                },
                multiply: {
                    inputs: ['第一个乘数', '第二个乘数', '第三个乘数', '第四个乘数', '第五个乘数', '第六个乘数', '第七个乘数', '第八个乘数', '第九个乘数', '第十个乘数'],
                    outputs: ['所有数的积']
                },
                divide: {
                    inputs: ['被除数', '除数'],
                    outputs: ['相除的结果']
                },
                power: {
                    inputs: ['底数', '指数'],
                    outputs: ['幂运算结果']
                }
            },
            function: {
                max: {
                    inputs: ['第一个数', '第二个数', '第三个数', '第四个数', '第五个数', '第六个数', '第七个数', '第八个数', '第九个数', '第十个数'],
                    outputs: ['最大值']
                },
                min: {
                    inputs: ['第一个数', '第二个数', '第三个数', '第四个数', '第五个数', '第六个数', '第七个数', '第八个数', '第九个数', '第十个数'],
                    outputs: ['最小值']
                },
                sqrt: {
                    inputs: ['待开方的数'],
                    outputs: ['平方根结果']
                },
                abs: {
                    inputs: ['待求绝对值的数'],
                    outputs: ['绝对值结果']
                },
                round: {
                    inputs: ['待四舍五入的数'],
                    outputs: ['四舍五入结果']
                }
            },
            condition: {
                controller: {
                    inputs: null,  // 动态生成 - 接收各分支结果
                    outputs: ['条件判断最终结果']
                },
                simple: {
                    inputs: ['判断条件', '条件为真时的值', '条件为假时的值'],
                    outputs: ['三目运算结果']
                },
                gt: {
                    inputs: ['左边的值', '右边的值'],
                    outputs: ['大于比较结果 (true/false)']
                },
                lt: {
                    inputs: ['左边的值', '右边的值'],
                    outputs: ['小于比较结果 (true/false)']
                },
                gte: {
                    inputs: ['左边的值', '右边的值'],
                    outputs: ['大于等于比较结果 (true/false)']
                },
                lte: {
                    inputs: ['左边的值', '右边的值'],
                    outputs: ['小于等于比较结果 (true/false)']
                },
                eq: {
                    inputs: ['左边的值', '右边的值'],
                    outputs: ['相等比较结果 (true/false)']
                },
                neq: {
                    inputs: ['左边的值', '右边的值'],
                    outputs: ['不等比较结果 (true/false)']
                },
                and: {
                    inputs: ['第一个布尔值', '第二个布尔值'],
                    outputs: ['逻辑与运算结果 (true/false)']
                },
                or: {
                    inputs: ['第一个布尔值', '第二个布尔值'],
                    outputs: ['逻辑或运算结果 (true/false)']
                },
                not: {
                    inputs: ['布尔值'],
                    outputs: ['逻辑非运算结果 (true/false)']
                }
            },
            branch: {
                if: {
                    inputs: ['if判断条件', 'if为真时的值'],
                    outputs: ['if分支结果']
                },
                elsif: {
                    inputs: ['elsif判断条件', 'elsif为真时的值'],
                    outputs: ['elsif分支结果']
                },
                else: {
                    inputs: ['else默认值'],
                    outputs: ['else分支结果']
                }
            },
            input: {
                number: {
                    outputs: ['数值参数']
                },
                string: {
                    outputs: ['字符串参数']
                },
                boolean: {
                    outputs: ['布尔值参数']
                }
            },
            constant: {
                number: {
                    outputs: ['数字常量值']
                },
                string: {
                    outputs: ['字符常值']
                },
                boolean: {
                    outputs: ['布尔常量值']
                }
            },
            output: {
                result: {
                    inputs: ['最终计算结果输入']
                }
            }
        };

        // 节点配置模板（包含端口类型定义）
        const nodeConfigs = {
            input: {
                number: { 
                    name: '数字输入', icon: '🔢', inputs: 0, outputs: 1,
                    outputTypes: ['number']
                },
                string: { 
                    name: '文本输入', icon: '📝', inputs: 0, outputs: 1,
                    outputTypes: ['string']
                },
                boolean: { 
                    name: '布尔输入', icon: '☑️', inputs: 0, outputs: 1,
                    outputTypes: ['boolean']
                }
            },
            math: {
                add: { 
                    name: '加法', icon: '➕', inputs: 2, outputs: 1, operator: '+', 
                    expandable: true, minInputs: 2, maxInputs: 10,
                    inputTypes: ['number'], outputTypes: ['number']
                },
                subtract: { 
                    name: '减法', icon: '➖', inputs: 2, outputs: 1, operator: '-', 
                    expandable: false, minInputs: 2, maxInputs: 2,
                    inputTypes: ['number'], outputTypes: ['number']
                },
                multiply: { 
                    name: '乘法', icon: '✖️', inputs: 2, outputs: 1, operator: '*', 
                    expandable: true, minInputs: 2, maxInputs: 10,
                    inputTypes: ['number'], outputTypes: ['number']
                },
                divide: { 
                    name: '除法', icon: '➗', inputs: 2, outputs: 1, operator: '/', 
                    expandable: false, minInputs: 2, maxInputs: 2,
                    inputTypes: ['number'], outputTypes: ['number']
                },
                power: { 
                    name: '幂运算', icon: '🔺', inputs: 2, outputs: 1, operator: '^', 
                    expandable: false, minInputs: 2, maxInputs: 2,
                    inputTypes: ['number'], outputTypes: ['number']
                }
            },
            function: {
                max: { 
                    name: '最大值', icon: '🔝', inputs: 2, outputs: 1, func: 'max', 
                    expandable: true, minInputs: 2, maxInputs: 10,
                    inputTypes: ['number'], outputTypes: ['number']
                },
                min: { 
                    name: '最小值', icon: '🔻', inputs: 2, outputs: 1, func: 'min', 
                    expandable: true, minInputs: 2, maxInputs: 10,
                    inputTypes: ['number'], outputTypes: ['number']
                },
                sqrt: { 
                    name: '平方根', icon: '√', inputs: 1, outputs: 1, func: 'sqrt', 
                    expandable: false, minInputs: 1, maxInputs: 1,
                    inputTypes: ['number'], outputTypes: ['number']
                },
                abs: { 
                    name: '绝对值', icon: '📏', inputs: 1, outputs: 1, func: 'abs', 
                    expandable: false, minInputs: 1, maxInputs: 1,
                    inputTypes: ['number'], outputTypes: ['number']
                },
                round: { 
                    name: '四舍五入', icon: '🔄', inputs: 1, outputs: 1, func: 'round', 
                    expandable: false, minInputs: 1, maxInputs: 1,
                    inputTypes: ['number'], outputTypes: ['number']
                },
                ceil: { 
                    name: '向上取整', icon: '⬆️', inputs: 1, outputs: 1, func: 'ceil', 
                    expandable: false, minInputs: 1, maxInputs: 1,
                    inputTypes: ['number'], outputTypes: ['number']
                },
                floor: { 
                    name: '向下取整', icon: '⬇️', inputs: 1, outputs: 1, func: 'floor', 
                    expandable: false, minInputs: 1, maxInputs: 1,
                    inputTypes: ['number'], outputTypes: ['number']
                }
            },
            condition: {
                controller: { 
                    name: '条件控制器', icon: '🎛️', inputs: 10, outputs: 1, 
                    expandable: true, minInputs: 2, maxInputs: 10,
                    inputTypes: ['any'], outputTypes: ['any']
                },
                simple: { 
                    name: '三目运算', icon: '❓', inputs: 3, outputs: 1, expandable: false,
                    inputTypes: ['boolean', 'any', 'any'], outputTypes: ['any']
                },
                gt: { 
                    name: '大于', icon: '▶️', inputs: 2, outputs: 1, expandable: false, operator: '>',
                    inputTypes: ['any', 'any'], outputTypes: ['boolean']
                },
                lt: { 
                    name: '小于', icon: '◀️', inputs: 2, outputs: 1, expandable: false, operator: '<',
                    inputTypes: ['any', 'any'], outputTypes: ['boolean']
                },
                gte: { 
                    name: '大于等于', icon: '⏩', inputs: 2, outputs: 1, expandable: false, operator: '>=',
                    inputTypes: ['any', 'any'], outputTypes: ['boolean']
                },
                lte: { 
                    name: '小于等于', icon: '⏪', inputs: 2, outputs: 1, expandable: false, operator: '<=',
                    inputTypes: ['any', 'any'], outputTypes: ['boolean']
                },
                eq: { 
                    name: '等于', icon: '🟰', inputs: 2, outputs: 1, expandable: false, operator: '==',
                    inputTypes: ['any', 'any'], outputTypes: ['boolean']
                },
                neq: { 
                    name: '不等于', icon: '≠', inputs: 2, outputs: 1, expandable: false, operator: '!=',
                    inputTypes: ['any', 'any'], outputTypes: ['boolean']
                },
                and: { 
                    name: '逻辑与', icon: '∧', inputs: 2, outputs: 1, expandable: false, operator: '&&',
                    inputTypes: ['boolean', 'boolean'], outputTypes: ['boolean']
                },
                or: { 
                    name: '逻辑或', icon: '∨', inputs: 2, outputs: 1, expandable: false, operator: '||',
                    inputTypes: ['boolean', 'boolean'], outputTypes: ['boolean']
                },
                not: { 
                    name: '逻辑非', icon: '¬', inputs: 1, outputs: 1, expandable: false, operator: '!',
                    inputTypes: ['boolean'], outputTypes: ['boolean']
                }
            },
            branch: {
                if: { 
                    name: 'if分支', icon: '🔵', inputs: 2, outputs: 1, expandable: false,
                    inputTypes: ['boolean', 'any'], outputTypes: ['any']
                },
                elsif: { 
                    name: 'elsif分支', icon: '🟡', inputs: 2, outputs: 1, expandable: false,
                    inputTypes: ['boolean', 'any'], outputTypes: ['any']
                },
                else: { 
                    name: 'else分支', icon: '🔴', inputs: 1, outputs: 1, expandable: false,
                    inputTypes: ['any'], outputTypes: ['any']
                }
            },
            constant: {
                number: { 
                    name: '数字', icon: '💯', inputs: 0, outputs: 1,
                    outputTypes: ['number']
                },
                string: { 
                    name: '字符', icon: '📝', inputs: 0, outputs: 1,
                    outputTypes: ['string']
                },
                boolean: { 
                    name: '布尔', icon: '✓✗', inputs: 0, outputs: 1,
                    outputTypes: ['boolean']
                }
            },
            output: {
                result: { 
                    name: '输出结果', icon: '🎯', inputs: 1, outputs: 0,
                    inputTypes: ['any']
                }
            }
        };

        // 初始化拖拽事件
        document.addEventListener('DOMContentLoaded', function() {
            initializeDragAndDrop();
            updateCanvasSize();
            initializeParameters();
            
            // 检查是否从首页跳转过来需要加载特定公式
            checkForFormulaToLoad();
            
            // 窗口大小变化时更新画布
            window.addEventListener('resize', updateCanvasSize);
            
            // 全局鼠标移动时隐藏tooltip（防止tooltip卡住）
            document.addEventListener('mousemove', function(e) {
                if (!e.target.classList.contains('node-port')) {
                    hidePortTooltip();
                }
            });
            
            // 添加键盘快捷键支持缩放
            document.addEventListener('keydown', function(e) {
                // Ctrl/Cmd + '+' 或 '=' 放大
                if ((e.ctrlKey || e.metaKey) && (e.key === '+' || e.key === '=')) {
                    e.preventDefault();
                    zoomIn();
                }
                // Ctrl/Cmd + '-' 缩小
                else if ((e.ctrlKey || e.metaKey) && e.key === '-') {
                    e.preventDefault();
                    zoomOut();
                }
                // Ctrl/Cmd + '0' 重置缩放
                else if ((e.ctrlKey || e.metaKey) && e.key === '0') {
                    e.preventDefault();
                    resetZoom();
                }
            });
            
            // 添加鼠标滚轮缩放支持（Ctrl + 滚轮）
            const canvasContainer = document.querySelector('.canvas-container');
            canvasContainer.addEventListener('wheel', function(e) {
                if (e.ctrlKey || e.metaKey) {
                    e.preventDefault();
                    
                    // deltaY > 0 表示向下滚动（缩小），< 0 表示向上滚动（放大）
                    if (e.deltaY < 0) {
                        zoomIn();
                    } else {
                        zoomOut();
                    }
                }
            }, { passive: false });
            
            // 监听滚动事件，更新连接线位置
            canvasContainer.addEventListener('scroll', function() {
                updateConnections();
            });
        });

        // 检查是否需要加载特定公式
        async function checkForFormulaToLoad() {
            const urlParams = new URLSearchParams(window.location.search);
            const formulaName = urlParams.get('formula');
            
            if (formulaName) {
                // 设置当前公式名称
                currentFormulaName = formulaName;
                
                // 更新页面标题
                document.title = `编辑公式: ${formulaName} - 公式设计器`;
                
                // 加载指定的公式
                await loadFormulaByName(formulaName);
            }
        }

        // 根据名称加载公式
        async function loadFormulaByName(formulaName) {
            try {
                const response = await fetch(`http://localhost:9999/api/formula/get/${encodeURIComponent(formulaName)}`);
                const result = await response.json();
                
                if (result.success && result.data) {
                    await loadFormula(result.data);
                } else {
                    alert(`❌ 加载公式失败: ${result.message || '公式不存在'}`);
                    // 如果加载失败，清除当前公式名称
                    currentFormulaName = null;
                }
            } catch (error) {
                alert(`❌ 加载公式失败: ${error.message}`);
                currentFormulaName = null;
            }
        }

        // 初始化参数管理
        function initializeParameters() {
            // 只有在没有从URL加载公式时才添加默认参数
            if (!currentFormulaName) {
            // 添加默认参数
            addParameter('length', 'number', 10, '长度');
            addParameter('width', 'number', 5, '宽度'); 
            addParameter('height', 'number', 3, '高度');
            updateParameterDisplay();
            }
        }

        // 显示端口提示
        function showPortTooltip(event, nodeId, portType, portIndex) {
            const tooltip = document.getElementById('portTooltip');
            const nodeData = nodes.get(nodeId);
            
            if (!nodeData || !tooltip) return;
            
            // 获取端口说明
            const description = getPortDescription(nodeData, portType, portIndex);
            if (!description) return;
            
            tooltip.textContent = description;
            
            // 智能位置计算，防止超出屏幕
            let left = event.pageX;
            let top = event.pageY - 45;
            
            // 防止右侧超出屏幕
            const tooltipWidth = tooltip.offsetWidth || 200;
            if (left + tooltipWidth > window.innerWidth) {
                left = window.innerWidth - tooltipWidth - 10;
            }
            
            // 防止顶部超出屏幕
            if (top < 10) {
                top = event.pageY + 20;
            }
            
            tooltip.style.left = left + 'px';
            tooltip.style.top = top + 'px';
            tooltip.classList.add('show');
        }

        // 隐藏端口提示
        function hidePortTooltip() {
            const tooltip = document.getElementById('portTooltip');
            if (tooltip) {
                tooltip.classList.remove('show');
            }
        }

        // 获取端口说明
        function getPortDescription(nodeData, portType, portIndex) {
            const type = nodeData.type;
            const subtype = nodeData.subtype;
            
            // 获取端口数据类型
            const dataType = getPortType(nodeData, portType, portIndex);
            const typeDisplay = {
                'number': '🔢数字',
                'string': '📝文本', 
                'boolean': '☑️布尔',
                'any': '🔄任意'
            }[dataType] || dataType;
            
            // 特殊处理参数节点
            if (type === 'input' && portType === 'output') {
                const paramName = nodeData.properties.paramName || '参数';
                return `输出参数: ${paramName} (${typeDisplay})`;
            }
            
            // 特殊处理条件控制器的动态端口描述
            if (type === 'condition' && subtype === 'controller' && portType === 'input') {
                return `第${portIndex + 1}个分支结果 (${typeDisplay})`;
            }
            
            if (!portDescriptions[type] || !portDescriptions[type][subtype]) {
                return `${portType === 'input' ? '输入' : '输出'}端口 (${typeDisplay})`;
            }
            
            const descriptions = portDescriptions[type][subtype];
            let baseDesc = '';
            
            if (portType === 'input' && descriptions.inputs) {
                baseDesc = descriptions.inputs[portIndex] || `第${portIndex + 1}个输入`;
            } else if (portType === 'output' && descriptions.outputs) {
                baseDesc = descriptions.outputs[portIndex] || `第${portIndex + 1}个输出`;
            }
            
            return baseDesc ? `${baseDesc} (${typeDisplay})` : null;
        }

        // 添加参数（新版：打开抽屉）
        function addParameter(name, type, defaultValue, description) {
            // 如果有参数传入，直接添加（用于初始化或加载）
            if (name) {
                if (!type) {
                    type = 'number';
                }
                if (defaultValue === undefined) {
                    defaultValue = type === 'number' ? 0 : '';
                }
                if (!description) {
                    description = name;
                }
                
                const paramId = `param_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
                globalParameters.set(paramId, {
                    id: paramId,
                    name: name,
                    type: type,
                    defaultValue: defaultValue,
                    description: description
                });
                updateParameterDisplay();
            } else {
                // 没有参数时，打开抽屉新增
                openParamDrawer();
            }
        }

        // 删除参数
        function removeParameter(paramId) {
            globalParameters.delete(paramId);
            updateParameterDisplay();
        }

        // 当前正在编辑的参数ID
        let currentEditingParamId = null;

        // 更新参数显示（新版：简洁列表）
        function updateParameterDisplay() {
            const parameterDiv = document.getElementById('parameterDefinitions');
            if (!parameterDiv) return;
            
            parameterDiv.innerHTML = '';
            
            // 获取类型对应的图标
            const typeIcons = {
                'number': '🔢',
                'string': '📝', 
                'boolean': '☑️'
            };

            const typeNames = {
                'number': '数字',
                'string': '文本', 
                'boolean': '布尔'
            };
            
            globalParameters.forEach((param, paramId) => {
                const paramItem = document.createElement('div');
                paramItem.className = 'param-list-item';
                paramItem.draggable = true;
                paramItem.dataset.paramId = paramId;
                
                paramItem.innerHTML = `
                    <div class="param-list-icon">${typeIcons[param.type] || '🔢'}</div>
                    <div class="param-list-info">
                        <div class="param-list-name">${param.name}</div>
                        <div class="param-list-meta">
                            <span class="param-list-type">${typeNames[param.type]}</span>
                            <span class="param-list-value">= ${param.defaultValue}</span>
                        </div>
                    </div>
                    <div class="param-list-drag-icon">⋮⋮</div>
                `;
                
                // 点击打开抽屉编辑
                paramItem.addEventListener('click', function(e) {
                    if (!e.target.classList.contains('param-list-drag-icon')) {
                        openParamDrawer(paramId);
                    }
                });
                
                // 添加拖拽事件
                paramItem.addEventListener('dragstart', function(e) {
                    e.dataTransfer.setData('text/plain', JSON.stringify({
                        type: 'input',
                        subtype: param.type,
                        paramId: paramId,
                        paramName: param.name
                    }));
                    this.classList.add('dragging');
                });
                
                paramItem.addEventListener('dragend', function(e) {
                    this.classList.remove('dragging');
                });
                
                parameterDiv.appendChild(paramItem);
            });
        }

        // 打开参数抽屉
        function openParamDrawer(paramId = null) {
            const drawer = document.getElementById('paramDrawer');
            const drawerIcon = document.getElementById('paramDrawerIcon');
            const drawerTitle = document.getElementById('paramDrawerTitle');
            const drawerBody = document.getElementById('paramDrawerBody');
            const deleteBtn = document.getElementById('paramDrawerDeleteBtn');
            
            currentEditingParamId = paramId;
            
            const typeIcons = {
                'number': '🔢',
                'string': '📝', 
                'boolean': '☑️'
            };
            
            if (paramId) {
                // 编辑模式
                const param = globalParameters.get(paramId);
                if (!param) return;
                
                drawerIcon.textContent = typeIcons[param.type] || '📝';
                drawerTitle.textContent = '编辑参数';
                deleteBtn.style.display = 'block';
                
                drawerBody.innerHTML = `
                    <div class="param-drawer-field">
                        <label class="param-drawer-label">参数名称 <span class="required">*</span></label>
                        <input type="text" class="param-drawer-input" id="paramDrawerName" 
                               value="${param.name}" placeholder="请输入参数名称">
                        <div class="param-drawer-hint">参数名称用于在公式中引用</div>
                    </div>
                    
                    <div class="param-drawer-field">
                        <label class="param-drawer-label">参数类型 <span class="required">*</span></label>
                        <select class="param-drawer-select" id="paramDrawerType">
                            <option value="number" ${param.type === 'number' ? 'selected' : ''}>数字 (Number)</option>
                            <option value="string" ${param.type === 'string' ? 'selected' : ''}>文本 (String)</option>
                            <option value="boolean" ${param.type === 'boolean' ? 'selected' : ''}>布尔 (Boolean)</option>
                        </select>
                        <div class="param-drawer-hint">选择参数的数据类型</div>
                    </div>
                    
                    <div class="param-drawer-field">
                        <label class="param-drawer-label">默认值</label>
                        <input type="text" class="param-drawer-input" id="paramDrawerValue" 
                               value="${param.defaultValue}" placeholder="请输入默认值">
                        <div class="param-drawer-hint">在测试运行时使用的默认值</div>
                    </div>
                    
                    <div class="param-drawer-field">
                        <label class="param-drawer-label">参数描述</label>
                        <textarea class="param-drawer-textarea" id="paramDrawerDesc" 
                                  placeholder="请输入参数描述（可选）">${param.description || ''}</textarea>
                        <div class="param-drawer-hint">对参数用途的简要说明</div>
                    </div>
                `;
            } else {
                // 新增模式
                drawerIcon.textContent = '➕';
                drawerTitle.textContent = '新增参数';
                deleteBtn.style.display = 'none';
                
                drawerBody.innerHTML = `
                    <div class="param-drawer-field">
                        <label class="param-drawer-label">参数名称 <span class="required">*</span></label>
                        <input type="text" class="param-drawer-input" id="paramDrawerName" 
                               placeholder="例如：length, width, price" autofocus>
                        <div class="param-drawer-hint">参数名称用于在公式中引用，建议使用英文或拼音</div>
                    </div>
                    
                    <div class="param-drawer-field">
                        <label class="param-drawer-label">参数类型 <span class="required">*</span></label>
                        <select class="param-drawer-select" id="paramDrawerType">
                            <option value="number" selected>数字 (Number)</option>
                            <option value="string">文本 (String)</option>
                            <option value="boolean">布尔 (Boolean)</option>
                        </select>
                        <div class="param-drawer-hint">选择参数的数据类型</div>
                    </div>
                    
                    <div class="param-drawer-field">
                        <label class="param-drawer-label">默认值</label>
                        <input type="text" class="param-drawer-input" id="paramDrawerValue" 
                               value="0" placeholder="请输入默认值">
                        <div class="param-drawer-hint">在测试运行时使用的默认值</div>
                    </div>
                    
                    <div class="param-drawer-field">
                        <label class="param-drawer-label">参数描述</label>
                        <textarea class="param-drawer-textarea" id="paramDrawerDesc" 
                                  placeholder="例如：商品的长度（单位：厘米）"></textarea>
                        <div class="param-drawer-hint">对参数用途的简要说明</div>
                    </div>
                `;
            }
            
            drawer.classList.add('show');
        }

        // 关闭参数抽屉
        function closeParamDrawer() {
            const drawer = document.getElementById('paramDrawer');
            drawer.classList.remove('show');
            currentEditingParamId = null;
        }

        // 从抽屉保存参数
        function saveParamFromDrawer() {
            const name = document.getElementById('paramDrawerName').value.trim();
            const type = document.getElementById('paramDrawerType').value;
            const value = document.getElementById('paramDrawerValue').value.trim();
            const description = document.getElementById('paramDrawerDesc').value.trim();
            
            if (!name) {
                alert('请输入参数名称！');
                return;
            }
            
            // 转换默认值
            let defaultValue = value;
            if (type === 'number') {
                const numValue = parseFloat(value);
                defaultValue = isNaN(numValue) ? 0 : numValue;
            } else if (type === 'boolean') {
                defaultValue = value === 'true' || value === '1' ? 'true' : 'false';
            }
            
            if (currentEditingParamId) {
                // 更新现有参数
                const param = globalParameters.get(currentEditingParamId);
                if (param) {
                    const oldName = param.name;
                    const oldType = param.type;
                    
                    param.name = name;
                    param.type = type;
                    param.defaultValue = defaultValue;
                    param.description = description;
                    
                    // 更新相关节点
                    if (oldName !== name) {
                        updateNodesUsingParameter(currentEditingParamId, oldName, name);
                    }
                    if (oldType !== type) {
                        updateParameterTypeInNodes(currentEditingParamId, type);
                    }
                    updateParameterDisplayInNodes(currentEditingParamId);
                }
            } else {
                // 新增参数
                const paramId = `param_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
                globalParameters.set(paramId, {
                    id: paramId,
                    name: name,
                    type: type,
                    defaultValue: defaultValue,
                    description: description
                });
            }
            
            updateParameterDisplay();
            closeParamDrawer();
        }

        // 从抽屉删除参数
        function deleteParamFromDrawer() {
            if (!currentEditingParamId) return;
            
            const param = globalParameters.get(currentEditingParamId);
            if (!param) return;
            
            if (confirm(`确定要删除参数 "${param.name}" 吗？`)) {
                globalParameters.delete(currentEditingParamId);
                updateParameterDisplay();
                closeParamDrawer();
            }
        }

        // 更新参数
        function updateParameter(paramId, property, value) {
            const param = globalParameters.get(paramId);
            if (param) {
                const oldName = param.name;
                
                if (property === 'defaultValue' && param.type === 'number') {
                    const numValue = parseFloat(value);
                    param[property] = isNaN(numValue) ? 0 : numValue;
                } else {
                    param[property] = value;
                }
                
                // 根据变更的属性更新相关节点
                if (property === 'name') {
                    updateNodesUsingParameter(paramId, oldName, value);
                } else if (property === 'type') {
                    updateParameterTypeInNodes(paramId, value);
                } else if (property === 'defaultValue' || property === 'description') {
                    // 默认值或描述变更时，更新节点显示
                    updateParameterDisplayInNodes(paramId);
                }
                
                // 重新显示参数列表以更新拖拽项
                updateParameterDisplay();
            }
        }
        
        // 更新参数在节点中的显示（用于默认值或描述变更）
        function updateParameterDisplayInNodes(paramId) {
            nodes.forEach(nodeData => {
                if (nodeData.type === 'input' && nodeData.properties.paramId === paramId) {
                    const param = globalParameters.get(paramId);
                    if (!param) return;
                    
                    // 更新节点的属性
                    nodeData.properties.defaultValue = param.defaultValue;
                    nodeData.properties.description = param.description;
                    
                    // 获取类型对应的图标
                    const typeIcons = {
                        'number': '🔢',
                        'string': '📝', 
                        'boolean': '☑️'
                    };
                    
                    // 更新节点显示
                    const titleElement = nodeData.element.querySelector('.node-title');
                    const contentElement = nodeData.element.querySelector('.node-content');
                    
                    if (titleElement) {
                        titleElement.textContent = `${typeIcons[param.type] || '🔢'} ${param.name}`;
                    }
                    
                    if (contentElement) {
                        contentElement.innerHTML = `
                            <div style="text-align: center; font-size: 14px; font-weight: 600; color: #007bff; background: white; padding: 8px 4px; border-radius: 2px;">${param.defaultValue}</div>
                        `;
                    }
                }
            });
        }

        // 设置输入端口数量
        function setInputCount(nodeId, newCount) {
            const nodeData = nodes.get(nodeId);
            if (!nodeData || !nodeData.config.expandable) return;
            
            const minInputs = nodeData.config.minInputs || 2;
            const maxInputs = nodeData.config.maxInputs || 10;
            
            // 限制输入数量在合理范围内
            newCount = Math.max(minInputs, Math.min(maxInputs, newCount));
            
            const currentInputs = nodeData.dynamicInputs || nodeData.config.inputs;
            
            if (newCount === currentInputs) return;
            
            // 如果减少输入数量，需要删除多余的连接
            if (newCount < currentInputs) {
                const connectionsToDelete = [];
                connections.forEach((connection, connectionId) => {
                    if (connection.to.nodeId === nodeId && connection.to.portIndex >= newCount) {
                        connectionsToDelete.push(connectionId);
                    }
                });
                
                connectionsToDelete.forEach(connectionId => {
                    connections.delete(connectionId);
                });
            }
            
            // 更新节点数据
            nodeData.dynamicInputs = newCount;
            
            // 重新创建端口
            const portsContainer = nodeData.element.querySelector('.node-ports');
            if (portsContainer) {
                portsContainer.outerHTML = createNodePorts(newCount, nodeData.config.outputs, nodeId, nodeData.config.expandable, nodeData.type, nodeData.subtype);
                
                // 重新绑定端口事件
                bindPortEvents(nodeData.element);
                
                // 更新连接线
                updateConnections();
                
                // 刷新属性面板
                if (selectedNode === nodeId) {
                    showNodeProperties(nodeData);
                }
            }
        }

        // 设置分支数量（专门用于条件控制器）
        function setBranchCount(controllerId, newBranchCount) {
            const controllerData = nodes.get(controllerId);
            if (!controllerData || controllerData.subtype !== 'controller') return;
            
            // 限制分支数量
            newBranchCount = Math.max(2, Math.min(10, newBranchCount));
            const currentBranchCount = controllerData.properties.branchCount || 2;
            
            if (newBranchCount === currentBranchCount) return;
            
            const currentBranches = controllerData.properties.branches || [];
            
            if (newBranchCount > currentBranchCount) {
                // 添加elsif分支
                const addCount = newBranchCount - currentBranchCount;
                const controllerX = controllerData.x;
                const branchY = controllerData.y - 120;
                
                for (let i = 0; i < addCount; i++) {
                    // elsif总是插入到else之前
                    const elsifBranchId = createBranchNode('elsif', controllerX, branchY, controllerId);
                    
                    // 将elsif插入到else之前
                    currentBranches.splice(currentBranches.length - 1, 0, elsifBranchId);
                }
            } else {
                // 删除多余的elsif分支（保留if和else）
                const removeCount = currentBranchCount - newBranchCount;
                
                // 找到所有elsif分支并删除多余的
                const allBranchNodes = currentBranches.map(id => nodes.get(id)).filter(n => n);
                const elsifBranches = allBranchNodes.filter(b => b.subtype === 'elsif');
                
                const branchesToRemove = elsifBranches.slice(-removeCount); // 删除最后添加的elsif
                
                branchesToRemove.forEach(branchData => {
                    deleteBranchNodeOnly(branchData.id);
                    const index = currentBranches.indexOf(branchData.id);
                    if (index > -1) currentBranches.splice(index, 1);
                });
            }
            
            // 更新控制器
            controllerData.properties.branchCount = newBranchCount;
            controllerData.dynamicInputs = newBranchCount;
            
            // 重新创建控制器端口
            const portsContainer = controllerData.element.querySelector('.node-ports');
            if (portsContainer) {
                portsContainer.outerHTML = createNodePorts(newBranchCount, 1, controllerId, true, 'condition', 'controller');
                bindPortEvents(controllerData.element);
            }
            
            // 重新排列分支位置
            repositionBranches(controllerId);
            
            // 重新连接所有分支到控制器
            setTimeout(() => {
                reconnectBranchesToController(controllerId);
                updateConnections();
                
                if (selectedNode === controllerId) {
                    showNodeProperties(controllerData);
                }
            }, 100);
        }

        // 重新排列分支位置
        function repositionBranches(controllerId) {
            const controllerData = nodes.get(controllerId);
            if (!controllerData) return;
            
            const branchIds = controllerData.properties.branches || [];
            const branchNodes = branchIds.map(id => nodes.get(id)).filter(n => n);
            
            // 按类型优先排序：if -> elsif -> else
            const sortOrder = {'if': 0, 'elsif': 1, 'else': 2};
            branchNodes.sort((a, b) => {
                const orderA = sortOrder[a.subtype] || 3;
                const orderB = sortOrder[b.subtype] || 3;
                return orderA - orderB;
            });
            
            const controllerX = controllerData.x;
            const branchY = controllerData.y - 120;
            const branchSpacing = 140;
            const startX = controllerX - ((branchNodes.length - 1) * branchSpacing) / 2;
            
            branchNodes.forEach((branchData, index) => {
                const newX = startX + (index * branchSpacing);
                branchData.element.style.left = newX + 'px';
                branchData.element.style.top = branchY + 'px';
                branchData.x = newX;
                branchData.y = branchY;
            });
            
            // 更新分支数组顺序
            controllerData.properties.branches = branchNodes.map(b => b.id);
        }

        // 重新连接分支到控制器
        function reconnectBranchesToController(controllerId) {
            const controllerData = nodes.get(controllerId);
            if (!controllerData) return;
            
            const branchIds = controllerData.properties.branches || [];
            const branchNodes = branchIds.map(id => nodes.get(id)).filter(n => n);
            
            // 按类型排序确保连接顺序：if -> elsif -> else
            const sortOrder = {'if': 0, 'elsif': 1, 'else': 2};
            branchNodes.sort((a, b) => {
                const orderA = sortOrder[a.subtype] || 3;
                const orderB = sortOrder[b.subtype] || 3;
                return orderA - orderB;
            });
            
            // 删除控制器的旧连接
            const connectionsToDelete = [];
            connections.forEach((connection, connectionId) => {
                if (connection.to.nodeId === controllerId) {
                    connectionsToDelete.push(connectionId);
                }
            });
            connectionsToDelete.forEach(id => connections.delete(id));
            
            // 按排序后的顺序重新连接
            branchNodes.forEach((branchData, index) => {
                createConnection({nodeId: branchData.id, portType: 'output', portIndex: 0}, 
                               {nodeId: controllerId, portType: 'input', portIndex: index});
            });
            
            // 更新控制器的分支数组顺序
            controllerData.properties.branches = branchNodes.map(b => b.id);
        }

        // 删除控制器组（包含所有分支）
        function deleteControllerGroup(controllerId) {
            const controllerData = nodes.get(controllerId);
            if (!controllerData) return;
            
            // 删除所有关联的分支节点
            const branches = controllerData.properties.branches || [];
            branches.forEach(branchId => {
                deleteBranchNodeOnly(branchId);
            });
            
            // 删除控制器本身
            deleteNode(controllerId);
        }

        // 删除单个分支节点（仅删除节点，不更新控制器）
        function deleteBranchNodeOnly(branchId) {
            const branchData = nodes.get(branchId);
            if (branchData) {
                // 删除相关连接
                const connectionsToDelete = [];
                connections.forEach((connection, connectionId) => {
                    if (connection.from.nodeId === branchId || connection.to.nodeId === branchId) {
                        connectionsToDelete.push(connectionId);
                    }
                });
                
                connectionsToDelete.forEach(connectionId => {
                    connections.delete(connectionId);
                });
                
                // 删除节点元素
                branchData.element.remove();
                nodes.delete(branchId);
            }
        }

        // 删除分支节点（由分支节点的关闭按钮调用）
        function deleteBranchNode(branchId, controllerId) {
            // 不允许删除分支节点，因为它们是控制器的一部分
            alert('分支节点是条件控制器的一部分，请删除整个控制器或调整分支数量。');
        }

        // 绑定端口事件
        function bindPortEvents(element) {
            // 重新绑定端口事件
            element.querySelectorAll('.node-port').forEach(port => {
                const nodeId = port.dataset.nodeId;
                const portType = port.dataset.portType;
                const portIndex = parseInt(port.dataset.portIndex);
                
                // 更新端口类型样式
                const nodeData = nodes.get(nodeId);
                if (nodeData) {
                    const dataType = getPortType(nodeData, portType, portIndex);
                    port.className = `node-port port-${portType} port-type-${dataType}`;
                }
                
                // 绑定点击事件
                port.onclick = function(event) {
                    startConnection(event, nodeId, portType, portIndex);
                };
                
                // 绑定悬停事件
                port.onmouseover = function(event) {
                    showPortTooltip(event, nodeId, portType, portIndex);
                };
                
                port.onmouseout = function(event) {
                    hidePortTooltip();
                };
            });
        }

        // 更新参数类型在节点中的体现
        function updateParameterTypeInNodes(paramId, newType) {
            nodes.forEach(nodeData => {
                if (nodeData.type === 'input' && nodeData.properties.paramId === paramId) {
                    // 更新节点的subtype
                    nodeData.subtype = newType;
                    nodeData.properties.type = newType;
                    
                    // 获取完整参数信息
                    const param = globalParameters.get(paramId);
                    if (!param) return;
                    
                    // 获取类型对应的图标
                    const typeIcons = {
                        'number': '🔢',
                        'string': '📝', 
                        'boolean': '☑️'
                    };
                    
                    // 更新节点显示
                    const titleElement = nodeData.element.querySelector('.node-title');
                    const contentElement = nodeData.element.querySelector('.node-content');
                    
                    if (titleElement) {
                        titleElement.textContent = `${typeIcons[newType] || '🔢'} ${param.name}`;
                    }
                    
                    if (contentElement) {
                        contentElement.innerHTML = `
                            <div style="text-align: center; font-size: 14px; font-weight: 600; color: #007bff; background: white; padding: 8px 4px; border-radius: 2px;">${param.defaultValue}</div>
                        `;
                    }
                    
                    // 更新端口颜色
                    const outputPorts = nodeData.element.querySelectorAll('.port-output');
                    outputPorts.forEach(port => {
                        port.className = `node-port port-output port-type-${newType}`;
                    });
                }
            });
        }

        // 更新使用指定参数的所有节点
        function updateNodesUsingParameter(paramId, oldName, newName) {
            nodes.forEach(nodeData => {
                if (nodeData.type === 'input' && nodeData.properties.paramId === paramId) {
                    // 更新节点属性
                    nodeData.properties.paramName = newName;
                    
                    // 获取完整参数信息
                    const param = globalParameters.get(paramId);
                    if (!param) return;
                    
                    // 获取类型对应的图标
                    const typeIcons = {
                        'number': '🔢',
                        'string': '📝', 
                        'boolean': '☑️'
                    };
                    
                    // 更新节点显示
                    const titleElement = nodeData.element.querySelector('.node-title');
                    const contentElement = nodeData.element.querySelector('.node-content');
                    
                    if (titleElement) {
                        titleElement.textContent = `${typeIcons[param.type] || '🔢'} ${newName}`;
                    }
                    
                    if (contentElement) {
                        contentElement.innerHTML = `
                            <div style="text-align: center; font-size: 14px; font-weight: 600; color: #007bff; background: white; padding: 8px 4px; border-radius: 2px;">${param.defaultValue}</div>
                        `;
                    }
                }
            });
        }

        // 初始化拖拽功能
        function initializeDragAndDrop() {
            // 节点面板的拖拽开始
            document.querySelectorAll('.node-item').forEach(item => {
                item.addEventListener('dragstart', function(e) {
                    const nodeType = this.dataset.nodeType;
                    const nodeSubtype = this.dataset.nodeSubtype;
                    e.dataTransfer.setData('text/plain', JSON.stringify({
                        type: nodeType,
                        subtype: nodeSubtype
                    }));
                    
                    // 添加拖拽效果
                    this.style.opacity = '0.5';
                });
                
                item.addEventListener('dragend', function(e) {
                    this.style.opacity = '1';
                });
            });

            // 画布的拖拽事件
            canvas.addEventListener('dragover', function(e) {
                e.preventDefault();
                document.getElementById('dropHint').style.display = nodes.size === 0 ? 'block' : 'none';
            });

            canvas.addEventListener('drop', function(e) {
                e.preventDefault();
                document.getElementById('dropHint').style.display = 'none';
                
                const data = JSON.parse(e.dataTransfer.getData('text/plain'));
                const rect = canvas.getBoundingClientRect();
                
                // 将屏幕坐标转换为逻辑坐标（考虑缩放因子）
                let x = (e.clientX - rect.left) / currentZoomScale;
                let y = (e.clientY - rect.top) / currentZoomScale;
                
                // 限制节点位置，防止被拖到画布外
                const minX = 10;  // 最小左边距
                const minY = 10;  // 最小上边距
                const maxX = 3000; // 最大右边界
                const maxY = 3000; // 最大下边界
                
                x = Math.max(minX, Math.min(maxX, x));
                y = Math.max(minY, Math.min(maxY, y));
                
                // 如果是从预定义参数拖拽的，传递额外信息
                if (data.paramId && data.paramName) {
                    createNodeFromParameter(data, x, y);
                } else {
                    createNode(data.type, data.subtype, x, y);
                }
            });
        }

        // 创建节点
        function createNode(type, subtype, x, y) {
            if (type === 'condition' && subtype === 'controller') {
                // 特殊处理：创建条件控制器时自动创建分支节点
                createControllerWithBranches(x, y);
                return;
            }
            
            const nodeId = `node_${nodeIdCounter++}`;
            const config = nodeConfigs[type][subtype];
            
            const nodeElement = document.createElement('div');
            let className = `canvas-node ${type}`;
            if (type === 'branch') {
                className += ` ${subtype}`;
            } else if (type === 'condition' && subtype === 'controller') {
                className += ` controller`;
            }
            nodeElement.className = className;
            nodeElement.id = nodeId;
            nodeElement.style.left = x + 'px';
            nodeElement.style.top = y + 'px';
            
            // 创建节点内容
            nodeElement.innerHTML = `
                <div class="node-header">
                    <span class="node-title">${config.icon} ${config.name}</span>
                    <button class="node-close" onclick="deleteNode('${nodeId}')">×</button>
                </div>
                <div class="node-content" id="${nodeId}_content">
                    ${getNodeContentHTML(type, subtype, nodeId)}
                </div>
                ${createNodePorts(config.inputs, config.outputs, nodeId, config.expandable, type, subtype)}
            `;
            
            canvas.appendChild(nodeElement);
            
            // 存储节点数据
            const nodeData = {
                id: nodeId,
                type: type,
                subtype: subtype,
                config: config,
                element: nodeElement,
                properties: getDefaultProperties(type, subtype),
                x: x,
                y: y,
                dynamicInputs: config.expandable ? config.inputs : null  // 动态输入端口数量
            };
            
            nodes.set(nodeId, nodeData);
            
            // 添加节点事件
            addNodeEvents(nodeElement, nodeData);
            
        }

        // 创建条件控制器及其分支节点
        function createControllerWithBranches(x, y) {
            // 创建条件控制器
            const controllerId = `node_${nodeIdCounter++}`;
            const controllerConfig = nodeConfigs.condition.controller;
            
            const controllerElement = document.createElement('div');
            controllerElement.className = `canvas-node condition controller`;
            controllerElement.id = controllerId;
            controllerElement.style.left = x + 'px';
            controllerElement.style.top = (y + 120) + 'px'; // 控制器在下方
            
            controllerElement.innerHTML = `
                <div class="node-header">
                    <span class="node-title">${controllerConfig.icon} ${controllerConfig.name}</span>
                    <button class="node-close" onclick="deleteControllerGroup('${controllerId}')">×</button>
                </div>
                <div class="node-content">
                    <div style="text-align: center; font-size: 10px; color: #4facfe; font-weight: bold;">条件控制器</div>
                </div>
                ${createNodePorts(2, 1, controllerId, true, 'condition', 'controller')}
            `;
            
            canvas.appendChild(controllerElement);
            
            // 存储控制器数据
            const controllerData = {
                id: controllerId,
                type: 'condition',
                subtype: 'controller',
                config: controllerConfig,
                element: controllerElement,
                properties: { branchCount: 2, branches: [] },
                x: x,
                y: y + 120,
                dynamicInputs: 2
            };
            
            nodes.set(controllerId, controllerData);
            addNodeEvents(controllerElement, controllerData);
            
            // 创建默认分支：if + else
            const ifBranchId = createBranchNode('if', x - 75, y, controllerId);
            const elseBranchId = createBranchNode('else', x + 75, y, controllerId);
            
            controllerData.properties.branches = [ifBranchId, elseBranchId];
            
            // 自动连接分支到控制器
            setTimeout(() => {
                createConnection({nodeId: ifBranchId, portType: 'output', portIndex: 0}, 
                               {nodeId: controllerId, portType: 'input', portIndex: 0});
                createConnection({nodeId: elseBranchId, portType: 'output', portIndex: 0}, 
                               {nodeId: controllerId, portType: 'input', portIndex: 1});
                
                // 选择控制器节点
                selectNode(controllerId);
            }, 100);
        }

        // 创建分支节点
        function createBranchNode(branchType, x, y, controllerId) {
            const branchId = `node_${nodeIdCounter++}`;
            const branchConfig = nodeConfigs.branch[branchType];
            
            const branchElement = document.createElement('div');
            branchElement.className = `canvas-node branch ${branchType}`;
            branchElement.id = branchId;
            branchElement.style.left = x + 'px';
            branchElement.style.top = y + 'px';
            
            branchElement.innerHTML = `
                <div class="node-header">
                    <span class="node-title">${branchConfig.icon} ${branchConfig.name}</span>
                    <button class="node-close" onclick="deleteBranchNode('${branchId}', '${controllerId}')">×</button>
                </div>
                <div class="node-content">
                    <div style="text-align: center; font-size: 10px; color: ${branchType === 'if' ? '#007bff' : branchType === 'elsif' ? '#ffc107' : '#dc3545'}; font-weight: bold;">${branchConfig.name}</div>
                </div>
                ${createNodePorts(branchConfig.inputs, branchConfig.outputs, branchId, false, 'branch', branchType)}
            `;
            
            canvas.appendChild(branchElement);
            
            // 存储分支数据
            const branchData = {
                id: branchId,
                type: 'branch',
                subtype: branchType,
                config: branchConfig,
                element: branchElement,
                properties: { branchType: branchType, controllerId: controllerId },
                x: x,
                y: y
            };
            
            nodes.set(branchId, branchData);
            addNodeEvents(branchElement, branchData);
            
            return branchId;
        }

        // 从预定义参数创建节点
        function createNodeFromParameter(data, x, y) {
            const nodeId = `node_${nodeIdCounter++}`;
            const param = globalParameters.get(data.paramId);
            
            if (!param) {
                return;
            }
            
            const config = nodeConfigs.input[data.subtype];
            
            const nodeElement = document.createElement('div');
            nodeElement.className = `canvas-node input`;
            nodeElement.id = nodeId;
            nodeElement.style.left = x + 'px';
            nodeElement.style.top = y + 'px';
            
            // 获取类型对应的图标
            const typeIcons = {
                'number': '🔢',
                'string': '📝', 
                'boolean': '☑️'
            };
            
            // 创建节点内容，显示完整参数信息
            nodeElement.innerHTML = `
                <div class="node-header">
                    <span class="node-title">${typeIcons[param.type] || '🔢'} ${param.name}</span>
                    <button class="node-close" onclick="deleteNode('${nodeId}')">×</button>
                </div>
                <div class="node-content">
                    <div style="text-align: center; font-size: 14px; font-weight: 600; color: #007bff; background: white; padding: 8px 4px; border-radius: 2px;">${param.defaultValue}</div>
                </div>
                ${createNodePorts(0, 1, nodeId, false, 'input', data.subtype)}
            `;
            
            canvas.appendChild(nodeElement);
            
            // 存储节点数据，自动设置参数信息
            const nodeData = {
                id: nodeId,
                type: 'input',
                subtype: data.subtype,
                config: config,
                element: nodeElement,
                properties: {
                    paramName: param.name,
                    defaultValue: param.defaultValue,
                    description: param.description,
                    type: param.type,
                    paramId: data.paramId
                },
                x: x,
                y: y,
                dynamicInputs: config.expandable ? config.inputs : null
            };
            
            nodes.set(nodeId, nodeData);
            
            // 添加节点事件
            addNodeEvents(nodeElement, nodeData);
            
        }

        // 获取节点内容HTML
        function getNodeContentHTML(type, subtype, nodeId) {
            switch(type) {
                case 'input':
                    // 输入节点现在只能通过拖拽预定义参数创建，不需要选择框
                    return `<div style="text-align: center; font-size: 10px; color: #666;">请从上方拖拽参数</div>`;
                case 'constant':
                    if (subtype === 'number') {
                        return `<input type="number" style="width: 100%; font-size: 14px; font-weight: 600; text-align: center;" value="0" onchange="updateNodeProperty('${nodeId}', 'value', this.value)" placeholder="输入数字">`;
                    } else if (subtype === 'string') {
                        return `<input type="text" style="width: 100%; font-size: 14px; font-weight: 600; text-align: center;" value="" onchange="updateNodeProperty('${nodeId}', 'value', this.value)" placeholder="输入文本">`;
                    } else if (subtype === 'boolean') {
                        return `<select style="width: 100%; font-size: 14px; font-weight: 600;" onchange="updateNodeProperty('${nodeId}', 'value', this.value)">
                                    <option value="true" selected>true</option>
                                    <option value="false">false</option>
                                </select>`;
                    }
                    break;
                case 'math':
                    return `<div style="text-align: center; font-weight: bold;">${nodeConfigs[type][subtype].operator}</div>`;
                case 'function':
                    return `<div style="text-align: center; font-weight: bold;">${nodeConfigs[type][subtype].func}()</div>`;
                case 'condition':
                    if (subtype === 'gt' || subtype === 'lt' || subtype === 'gte' || 
                        subtype === 'lte' || subtype === 'eq' || subtype === 'neq') {
                        // 独立的比较运算节点，直接显示运算符
                        return `<div style="text-align: center; font-weight: bold; font-size: 18px;">${nodeConfigs[type][subtype].operator}</div>`;
                    } else if (subtype === 'and' || subtype === 'or' || subtype === 'not') {
                        // 独立的逻辑运算节点，直接显示运算符
                        return `<div style="text-align: center; font-weight: bold; font-size: 18px;">${nodeConfigs[type][subtype].operator}</div>`;
                    } else if (subtype === 'controller') {
                        return `<div style="text-align: center; font-size: 10px; color: #4facfe; font-weight: bold;">条件控制器</div>`;
                    } else if (subtype === 'simple') {
                        return `<div style="text-align: center; font-size: 10px;">条件 ? 真值 : 假值</div>`;
                    } else {
                        return `<div style="text-align: center; font-size: 10px;">条件判断</div>`;
                    }
                
                case 'branch':
                    if (subtype === 'if') {
                        return `<div style="text-align: center; font-size: 10px; color: #007bff; font-weight: bold;">if分支</div>`;
                    } else if (subtype === 'elsif') {
                        return `<div style="text-align: center; font-size: 10px; color: #ffc107; font-weight: bold;">elsif分支</div>`;
                    } else if (subtype === 'else') {
                        return `<div style="text-align: center; font-size: 10px; color: #dc3545; font-weight: bold;">else分支</div>`;
                    }
                    break;
                case 'output':
                    return `<div style="text-align: center; font-size: 11px; font-weight: bold; color: #333;">计算结果</div>`;
                default:
                    return '';
            }
        }

        // 创建节点端口
        function createNodePorts(inputCount, outputCount, nodeId, expandable = false, nodeType = null, nodeSubtype = null) {
            let portsHTML = '<div class="node-ports" id="' + nodeId + '_ports">';
            
            // 统一布局：所有节点的输入端口都在顶部，输出端口都在底部
            
            // 输入端口在顶部
            if (inputCount > 0) {
                const nodeWidth = 120; // 节点宽度
                const portSpacing = Math.min(25, nodeWidth / Math.max(inputCount, 1));
                const totalWidth = (inputCount - 1) * portSpacing;
                const startOffset = (nodeWidth - totalWidth) / 2;
                
                for (let i = 0; i < inputCount; i++) {
                    const left = Math.max(10, Math.min(nodeWidth - 20, startOffset + (i * portSpacing)));
                    const typeClass = getPortTypeClass(nodeId, 'input', i, nodeType, nodeSubtype);
                    portsHTML += `<div class="node-port port-input ${typeClass}" 
                                       data-port-type="input" 
                                       data-port-index="${i}" 
                                       data-node-id="${nodeId}" 
                                       style="left: ${left}px; top: -6px;" 
                                       onclick="startConnection(event, '${nodeId}', 'input', ${i})"
                                       onmouseover="showPortTooltip(event, '${nodeId}', 'input', ${i})"
                                       onmouseout="hidePortTooltip()"></div>`;
                }
            }
            
            // 输出端口在底部
            if (outputCount > 0) {
                const nodeWidth = 120; // 节点宽度
                const portSpacing = Math.min(25, nodeWidth / Math.max(outputCount, 1));
                const totalWidth = (outputCount - 1) * portSpacing;
                const startOffset = (nodeWidth - totalWidth) / 2;
                
                for (let i = 0; i < outputCount; i++) {
                    const left = outputCount === 1 ? 
                        '50%' : // 单个输出端口居中
                        `${Math.max(10, Math.min(nodeWidth - 20, startOffset + (i * portSpacing)))}px`;
                    
                    const typeClass = getPortTypeClass(nodeId, 'output', i, nodeType, nodeSubtype);
                    const transform = outputCount === 1 ? 'transform: translateX(-50%);' : '';
                    
                    portsHTML += `<div class="node-port port-output ${typeClass}" 
                                       data-port-type="output" 
                                       data-port-index="${i}" 
                                       data-node-id="${nodeId}" 
                                       style="left: ${left}; bottom: -6px; ${transform}" 
                                       onclick="startConnection(event, '${nodeId}', 'output', ${i})"
                                       onmouseover="showPortTooltip(event, '${nodeId}', 'output', ${i})"
                                       onmouseout="hidePortTooltip()"></div>`;
                }
            }
            
            portsHTML += '</div>';
            return portsHTML;
        }

        // 获取端口类型CSS类
        function getPortTypeClass(nodeId, portType, portIndex, nodeType, nodeSubtype) {
            // 对于还在创建过程中的节点，需要特殊处理
            let nodeData = nodes.get(nodeId);
            
            // 如果节点还未创建完成，根据nodeType和subtype推断
            if (!nodeData && nodeType) {
                // 根据不同节点类型获取类型
                if (nodeType === 'branch') {
                    // 分支节点类型固定
                    if (portType === 'input') {
                        return portIndex === 0 ? 'port-type-boolean' : 'port-type-any'; // 第一个是条件(布尔)，第二个是值(任意)
                    } else {
                        return 'port-type-any'; // 输出任意类型
                    }
                } else if (nodeType === 'condition') {
                    // 三目运算特殊处理
                    if (nodeSubtype === 'simple' && portType === 'input') {
                        if (portIndex === 0) return 'port-type-boolean'; // 条件必须是布尔
                        return 'port-type-any'; // 值可以是任意类型
                    } else if (nodeSubtype === 'gt' || nodeSubtype === 'lt' || 
                               nodeSubtype === 'gte' || nodeSubtype === 'lte' || 
                               nodeSubtype === 'eq' || nodeSubtype === 'neq') {
                        // 独立的比较运算节点
                        return portType === 'input' ? 'port-type-any' : 'port-type-boolean';
                    } else if (nodeSubtype === 'and' || nodeSubtype === 'or' || nodeSubtype === 'not') {
                        // 独立的逻辑运算节点
                        return 'port-type-boolean'; // 逻辑运算的输入和输出都是布尔
                    }
                    return 'port-type-any'; // 条件控制器接受任意类型
                } else if (nodeType === 'math' || nodeType === 'function') {
                    return 'port-type-number'; // 数学运算都是数字类型
                } else if (nodeType === 'input') {
                    return 'port-type-number'; // 默认数字参数
                }
                return 'port-type-any';
            }
            
            if (!nodeData) return 'port-type-any';
            
            const dataType = getPortType(nodeData, portType, portIndex);
            return `port-type-${dataType}`;
        }

         // 获取默认属性
         function getDefaultProperties(type, subtype) {
             const defaults = {
                 input: { paramName: '', defaultValue: '', description: '' },
                 math: { operator: nodeConfigs[type][subtype].operator },
                 function: { 
                     functionName: nodeConfigs[type][subtype].func, 
                     parameters: [],
                     // round 函数特有属性：保留小数位数
                     decimalPlaces: subtype === 'round' ? 0 : undefined
                 },
                 condition: { 
                     operator: nodeConfigs.condition[subtype]?.operator || (subtype === 'logic' ? '&&' : ''),
                     branchCount: 3  // 控制器默认管理3个分支
                 },
                 branch: {
                     condition: '',
                     value: '',
                     branchType: subtype
                 },
                 constant: {
                     value: subtype === 'number' ? '0' : (subtype === 'boolean' ? 'true' : ''),
                     valueType: subtype
                 },
                 output: { resultName: 'result' }
             };
             
             return defaults[type] || {};
         }

        // 添加节点事件
        function addNodeEvents(element, nodeData) {
            // 点击选择
            element.addEventListener('click', function(e) {
                e.stopPropagation();
                selectNode(nodeData.id);
            });
            
            // 拖拽移动
            element.addEventListener('mousedown', function(e) {
                if (e.target.classList.contains('node-close') || 
                    e.target.classList.contains('node-port') ||
                    e.target.tagName === 'INPUT' || 
                    e.target.tagName === 'SELECT') {
                    return;
                }
                
                isDragging = true;
                const rect = element.getBoundingClientRect();
                const canvasRect = canvas.getBoundingClientRect();
                
                // 计算偏移量时考虑缩放因子
                // getBoundingClientRect返回的是缩放后的坐标，需要转换为逻辑坐标
                dragOffset.x = (e.clientX - rect.left) / currentZoomScale;
                dragOffset.y = (e.clientY - rect.top) / currentZoomScale;
                
                element.style.zIndex = 1000;
                selectNode(nodeData.id);
            });
        }

        // 全局鼠标事件
        let dragUpdateTimeout = null;
        document.addEventListener('mousemove', function(e) {
            if (isDragging && selectedNode) {
                const canvasRect = canvas.getBoundingClientRect();
                
                // 将屏幕坐标转换为逻辑坐标（考虑缩放因子）
                const logicalX = (e.clientX - canvasRect.left) / currentZoomScale;
                const logicalY = (e.clientY - canvasRect.top) / currentZoomScale;
                
                // 减去拖动偏移量得到节点的逻辑位置
                let x = logicalX - dragOffset.x;
                let y = logicalY - dragOffset.y;
                
                // 限制节点位置，防止被拖到画布外
                const minX = 10;  // 最小左边距
                const minY = 10;  // 最小上边距
                const maxX = 3000; // 最大右边界（给足够的空间）
                const maxY = 3000; // 最大下边界
                
                x = Math.max(minX, Math.min(maxX, x));
                y = Math.max(minY, Math.min(maxY, y));
                
                const nodeData = nodes.get(selectedNode);
                if (nodeData) {
                    nodeData.element.style.left = x + 'px';
                    nodeData.element.style.top = y + 'px';
                    nodeData.x = x;
                    nodeData.y = y;
                    
                    // 使用节流更新连接线，避免频繁更新导致的性能问题
                    if (dragUpdateTimeout) {
                        clearTimeout(dragUpdateTimeout);
                    }
                    dragUpdateTimeout = setTimeout(() => {
                        updateConnections();
                    }, 16); // 约60fps
                }
            }
        });

        document.addEventListener('mouseup', function(e) {
            if (isDragging) {
                isDragging = false;
                if (selectedNode) {
                    const nodeData = nodes.get(selectedNode);
                    if (nodeData) {
                        nodeData.element.style.zIndex = '';
                    }
                }
                
                // 拖动结束后，延迟更新连接线确保DOM已完全更新
                if (dragUpdateTimeout) {
                    clearTimeout(dragUpdateTimeout);
                    dragUpdateTimeout = null;
                }
                
                // 使用requestAnimationFrame + setTimeout确保精确更新
                requestAnimationFrame(() => {
                    requestAnimationFrame(() => {
                        setTimeout(() => {
                            updateConnections();
                        }, 50);
                    });
                });
            }
        });

        // 点击画布空白处取消选择
        canvas.addEventListener('click', function(e) {
            if (e.target === canvas) {
                selectNode(null);
            }
        });

        // 选择节点
        function selectNode(nodeId) {
            // 取消之前的选择
            document.querySelectorAll('.canvas-node.selected').forEach(node => {
                node.classList.remove('selected');
            });
            
            selectedNode = nodeId;
            
            if (nodeId) {
                const nodeData = nodes.get(nodeId);
                if (nodeData) {
                    nodeData.element.classList.add('selected');
                    showNodeProperties(nodeData);
                }
            } else {
                showDefaultProperties();
            }
        }

        // 显示节点属性
        function showNodeProperties(nodeData) {
            const propertyContent = document.getElementById('propertyContent');
            const config = nodeData.config;
            
            let propertiesHTML = `
                <div class="property-section">
                    <div class="section-title">${config.icon} ${config.name}</div>
                    
                    <div class="form-group">
                        <label class="form-label">节点ID</label>
                        <input type="text" class="form-input" value="${nodeData.id}" readonly>
                    </div>
            `;
            
            // 根据节点类型添加不同的配置项
            switch(nodeData.type) {
                case 'input':
                    propertiesHTML += `
                        <div class="form-group">
                            <label class="form-label">参数名称</label>
                            <input type="text" class="form-input" value="${nodeData.properties.paramName || ''}" 
                                   onchange="updateNodeProperty('${nodeData.id}', 'paramName', this.value)">
                        </div>
                        <div class="form-group">
                            <label class="form-label">默认值</label>
                            <input type="text" class="form-input" value="${nodeData.properties.defaultValue || ''}"
                                   onchange="updateNodeProperty('${nodeData.id}', 'defaultValue', this.value)">
                        </div>
                        <div class="form-group">
                            <label class="form-label">参数描述</label>
                            <textarea class="form-textarea" onchange="updateNodeProperty('${nodeData.id}', 'description', this.value)">${nodeData.properties.description || ''}</textarea>
                        </div>
                    `;
                    break;
                    
                case 'math':
                    propertiesHTML += `
                        <div class="form-group">
                            <label class="form-label">运算符</label>
                            <div style="font-size: 14px; font-weight: bold; text-align: center; padding: 8px; background: #f8f9fa; border-radius: 4px;">
                                ${nodeData.config.operator} (${nodeData.config.name})
                            </div>
                        </div>
                    `;
                    
                    // 如果是可扩展节点，添加输入数量设置
                    if (nodeData.config.expandable) {
                        const currentInputs = nodeData.dynamicInputs || nodeData.config.inputs;
                        const minInputs = nodeData.config.minInputs || 2;
                        const maxInputs = nodeData.config.maxInputs || 10;
                        
                        propertiesHTML += `
                            <div class="form-group">
                                <label class="form-label">输入数量设置</label>
                                <div style="display: flex; align-items: center; gap: 8px;">
                                    <input type="number" 
                                           value="${currentInputs}" 
                                           min="${minInputs}" 
                                           max="${maxInputs}"
                                           class="form-input"
                                           style="width: 80px;"
                                           onchange="setInputCount('${nodeData.id}', parseInt(this.value))">
                                    <span style="font-size: 12px; color: #666;">个输入端口</span>
                                </div>
                                <div style="font-size: 11px; color: #999; margin-top: 4px;">
                                    范围: ${minInputs} - ${maxInputs} 个输入
                                </div>
                                <div style="font-size: 11px; color: #666; margin-top: 2px;">
                                    ${nodeData.subtype === 'add' ? '多个数相加: a + b + c + ...' : 
                                     nodeData.subtype === 'multiply' ? '多个数相乘: a × b × c × ...' : '数学运算'}
                                </div>
                            </div>
                        `;
                    } else {
                        // 不可扩展节点的说明
                        propertiesHTML += `
                            <div class="form-group">
                                <label class="form-label">输入端口</label>
                                <div style="font-size: 12px; color: #666; padding: 8px; background: #f8f9fa; border-radius: 4px;">
                                    ${nodeData.config.inputs} 个输入端口 (固定)
                                    <div style="font-size: 11px; margin-top: 2px;">
                                        ${nodeData.subtype === 'divide' ? '除法必须是两个数: 被除数 ÷ 除数' :
                                          nodeData.subtype === 'subtract' ? '减法必须是两个数: 被减数 - 减数' :
                                          nodeData.subtype === 'power' ? '幂运算必须是两个数: 底数 ^ 指数' :
                                          '此运算固定输入数量'}
                                    </div>
                                </div>
                            </div>
                        `;
                    }
                    break;
                    
                case 'function':
                    propertiesHTML += `
                        <div class="form-group">
                            <label class="form-label">函数名</label>
                            <div style="font-size: 14px; font-weight: bold; text-align: center; padding: 8px; background: #f8f9fa; border-radius: 4px;">
                                ${nodeData.config.func}() (${nodeData.config.name})
                            </div>
                        </div>
                    `;
                    
                    // 如果函数支持可变参数
                    if (nodeData.config.expandable) {
                        const currentInputs = nodeData.dynamicInputs || nodeData.config.inputs;
                        const minInputs = nodeData.config.minInputs || 2;
                        const maxInputs = nodeData.config.maxInputs || 10;
                        
                        propertiesHTML += `
                            <div class="form-group">
                                <label class="form-label">参数数量设置</label>
                                <div style="display: flex; align-items: center; gap: 8px;">
                                    <input type="number" 
                                           value="${currentInputs}" 
                                           min="${minInputs}" 
                                           max="${maxInputs}"
                                           class="form-input"
                                           style="width: 80px;"
                                           onchange="setInputCount('${nodeData.id}', parseInt(this.value))">
                                    <span style="font-size: 12px; color: #666;">个参数</span>
                                </div>
                                <div style="font-size: 11px; color: #999; margin-top: 4px;">
                                    范围: ${minInputs} - ${maxInputs} 个参数
                                </div>
                                <div style="font-size: 11px; color: #666; margin-top: 2px;">
                                    ${nodeData.subtype === 'max' ? 'max(a, b, c, ...)' : 
                                     nodeData.subtype === 'min' ? 'min(a, b, c, ...)' : '函数调用'}
                                </div>
                            </div>
                        `;
                    } else {
                        propertiesHTML += `
                            <div class="form-group">
                                <label class="form-label">函数参数</label>
                                <div style="font-size: 12px; color: #666; padding: 8px; background: #f8f9fa; border-radius: 4px;">
                                    ${nodeData.config.inputs} 个参数 (固定)
                                    <div style="font-size: 11px; margin-top: 2px;">
                                        ${nodeData.subtype === 'sqrt' ? '平方根: sqrt(x)' :
                                          nodeData.subtype === 'abs' ? '绝对值: abs(x)' :
                                          nodeData.subtype === 'round' ? '四舍五入: round(x)' :
                                          nodeData.subtype === 'ceil' ? '向上取整: ceil(x)' :
                                          nodeData.subtype === 'floor' ? '向下取整: floor(x)' :
                                          '此函数固定参数数量'}
                                    </div>
                                </div>
                            </div>
                        `;
                        
                        // round 函数特有：保留小数位数设置
                        if (nodeData.subtype === 'round') {
                            const decimalPlaces = nodeData.properties.decimalPlaces !== undefined ? nodeData.properties.decimalPlaces : 0;
                            propertiesHTML += `
                                <div class="form-group">
                                    <label class="form-label">保留小数位数</label>
                                    <div style="display: flex; align-items: center; gap: 8px;">
                                        <input type="number" 
                                               value="${decimalPlaces}" 
                                               min="0" 
                                               max="10"
                                               class="form-input"
                                               style="width: 80px;"
                                               onchange="updateNodeProperty('${nodeData.id}', 'decimalPlaces', parseInt(this.value))">
                                        <span style="font-size: 12px; color: #666;">位小数</span>
                                    </div>
                                    <div style="font-size: 11px; color: #999; margin-top: 4px;">
                                        0 = 四舍五入到整数，1 = 保留1位小数，2 = 保留2位小数...
                                    </div>
                                    <div style="font-size: 11px; color: #666; margin-top: 4px; padding: 6px; background: #fff3cd; border-radius: 3px;">
                                        💡 例如：保留2位小数会生成表达式 <code>round(x * 100) / 100.0</code>
                                    </div>
                                </div>
                            `;
                        }
                    }
                    break;
                    
                case 'condition':
                    if (nodeData.subtype === 'gt' || nodeData.subtype === 'lt' || 
                        nodeData.subtype === 'gte' || nodeData.subtype === 'lte' || 
                        nodeData.subtype === 'eq' || nodeData.subtype === 'neq') {
                        // 独立的比较运算节点，显示固定的运算符
                        const operatorName = {
                            'gt': '大于 (>)',
                            'lt': '小于 (<)',
                            'gte': '大于等于 (>=)',
                            'lte': '小于等于 (<=)',
                            'eq': '等于 (==)',
                            'neq': '不等于 (!=)'
                        }[nodeData.subtype] || nodeData.properties.operator;
                        
                        propertiesHTML += `
                            <div class="form-group">
                                <label class="form-label">比较操作符</label>
                                <div style="font-size: 14px; font-weight: bold; text-align: center; padding: 8px; background: #f8f9fa; border-radius: 4px;">
                                    ${operatorName}
                                </div>
                            </div>
                            <div class="form-group">
                                <label class="form-label">说明</label>
                                <div style="font-size: 12px; color: #666; padding: 8px; background: #f8f9fa; border-radius: 4px;">
                                    将左边的值与右边的值进行比较，返回布尔值 (true/false)
                                </div>
                            </div>
                        `;
                    } else if (nodeData.subtype === 'and' || nodeData.subtype === 'or' || nodeData.subtype === 'not') {
                        // 独立的逻辑运算节点，显示固定的运算符
                        const operatorName = {
                            'and': '逻辑与 (&&)',
                            'or': '逻辑或 (||)',
                            'not': '逻辑非 (!)'
                        }[nodeData.subtype] || nodeData.properties.operator;
                        
                        const description = {
                            'and': '两个条件都为真时返回 true，否则返回 false',
                            'or': '两个条件中至少有一个为真时返回 true，否则返回 false',
                            'not': '对布尔值取反，true 变为 false，false 变为 true'
                        }[nodeData.subtype] || '逻辑运算';
                        
                        propertiesHTML += `
                            <div class="form-group">
                                <label class="form-label">逻辑操作符</label>
                                <div style="font-size: 14px; font-weight: bold; text-align: center; padding: 8px; background: #f8f9fa; border-radius: 4px;">
                                    ${operatorName}
                                </div>
                            </div>
                            <div class="form-group">
                                <label class="form-label">说明</label>
                                <div style="font-size: 12px; color: #666; padding: 8px; background: #f8f9fa; border-radius: 4px;">
                                    ${description}
                                </div>
                            </div>
                        `;
                    } else if (nodeData.subtype === 'controller') {
                        const currentBranchCount = nodeData.properties.branchCount || 2;
                        const branches = nodeData.properties.branches || [];
                        
                        propertiesHTML += `
                            <div class="form-group">
                                <label class="form-label">分支数量管理</label>
                                <div style="display: flex; align-items: center; gap: 8px;">
                                    <input type="number" 
                                           value="${currentBranchCount}" 
                                           min="2" 
                                           max="10"
                                           class="form-input"
                                           style="width: 80px;"
                                           onchange="setBranchCount('${nodeData.id}', parseInt(this.value))">
                                    <span style="font-size: 12px; color: #666;">个分支</span>
                                </div>
                                <div style="font-size: 11px; color: #999; margin-top: 4px;">
                                    范围: 2-10 个分支 (最小包含if+else)
                                </div>
                            </div>
                            <div class="form-group">
                                <label class="form-label">当前分支结构</label>
                                <div style="font-size: 11px; color: #666; background: #f8f9fa; padding: 8px; border-radius: 4px;">
                                    <div style="margin-bottom: 4px;">
                                        🔵 if分支: 始终存在<br/>
                                        ${currentBranchCount > 2 ? `🟡 elsif分支: ${currentBranchCount - 2}个<br/>` : ''}
                                        🔴 else分支: 始终存在
                                    </div>
                                    <div style="font-size: 10px; color: #999; margin-top: 6px; padding-top: 6px; border-top: 1px solid #eee;">
                                        • 修改数量会自动添加/删除分支节点<br/>
                                        • 分支节点会自动连接到控制器<br/>
                                        • 分支按优先级排序: if → elsif → else
                                    </div>
                                </div>
                            </div>
                            <div class="form-group">
                                <label class="form-label">分支连接状态</label>
                                <div style="font-size: 11px; color: #666;">
                                    已连接分支: ${branches.length} 个
                                </div>
                            </div>
                        `;
                    } else {
                        propertiesHTML += `
                            <div class="form-group">
                                <label class="form-label">三目运算</label>
                                <div style="font-size: 12px; color: #666;">
                                    condition ? trueValue : falseValue
                                </div>
                            </div>
                        `;
                    }
                    break;
                    
                case 'constant':
                    if (nodeData.subtype === 'number') {
                        propertiesHTML += `
                            <div class="form-group">
                                <label class="form-label">常量值</label>
                                <input type="number" class="form-input" value="${nodeData.properties.value || '0'}" 
                                       onchange="updateNodeProperty('${nodeData.id}', 'value', this.value)" placeholder="输入数字">
                            </div>
                            <div class="form-group">
                                <label class="form-label">说明</label>
                                <div style="font-size: 12px; color: #666; background: #f8f9fa; padding: 8px; border-radius: 4px;">
                                    💯 数字常量可用于数学运算和比较判断，例如：判断结果是否大于 0
                                </div>
                            </div>
                        `;
                    } else if (nodeData.subtype === 'string') {
                        propertiesHTML += `
                            <div class="form-group">
                                <label class="form-label">常量值</label>
                                <input type="text" class="form-input" value="${nodeData.properties.value || ''}" 
                                       onchange="updateNodeProperty('${nodeData.id}', 'value', this.value)" placeholder="输入文本">
                            </div>
                            <div class="form-group">
                                <label class="form-label">说明</label>
                                <div style="font-size: 12px; color: #666; background: #f8f9fa; padding: 8px; border-radius: 4px;">
                                    📝 字符常量用于文本比较，例如：判断颜色是否等于 '红'
                                    <div style="font-size: 11px; margin-top: 4px; color: #999;">
                                        注意：在公式中会自动添加单引号
                                    </div>
                                </div>
                            </div>
                        `;
                    } else if (nodeData.subtype === 'boolean') {
                        propertiesHTML += `
                            <div class="form-group">
                                <label class="form-label">常量值</label>
                                <select class="form-select" onchange="updateNodeProperty('${nodeData.id}', 'value', this.value)">
                                    <option value="true" ${nodeData.properties.value === 'true' ? 'selected' : ''}>true</option>
                                    <option value="false" ${nodeData.properties.value === 'false' ? 'selected' : ''}>false</option>
                                </select>
                            </div>
                            <div class="form-group">
                                <label class="form-label">说明</label>
                                <div style="font-size: 12px; color: #666; background: #f8f9fa; padding: 8px; border-radius: 4px;">
                                    ✓✗ 布尔常量用于逻辑判断，可选值：true 或 false
                                </div>
                            </div>
                        `;
                    }
                    break;
                
                case 'branch':
                    propertiesHTML += `
                        <div class="form-group">
                            <label class="form-label">分支类型</label>
                            <div style="font-size: 14px; font-weight: bold; text-align: center; padding: 8px; background: #f8f9fa; border-radius: 4px;">
                                ${nodeData.config.icon} ${nodeData.config.name}
                            </div>
                        </div>
                        <div class="form-group">
                            <label class="form-label">分支说明</label>
                            <div style="font-size: 12px; color: #666; background: #f8f9fa; padding: 8px; border-radius: 4px;">
                                ${nodeData.subtype === 'if' ? 
                                    '🔵 if分支: 第一个要检查的条件，如果满足则执行此分支' :
                                nodeData.subtype === 'elsif' ?
                                    '🟡 elsif分支: 当前面的条件都不满足时检查此条件' :
                                    '🔴 else分支: 当所有条件都不满足时的默认分支'}
                            </div>
                        </div>
                        <div class="form-group">
                            <label class="form-label">使用步骤</label>
                            <div style="font-size: 11px; color: #666;">
                                <div>1. 连接${nodeData.subtype === 'else' ? '' : '条件和'}值到此分支</div>
                                <div>2. 将分支结果连接到条件控制器</div>
                                <div>3. 控制器将按优先级选择分支</div>
                            </div>
                        </div>
                    `;
                    break;
                    
                case 'output':
                    propertiesHTML += `
                        <div class="form-group">
                            <label class="form-label">输出结果</label>
                            <div style="font-size: 12px; color: #666; padding: 8px; background: #f8f9fa; border-radius: 4px;">
                                📊 最终计算结果
                                <div style="font-size: 11px; margin-top: 2px;">
                                    此节点将输出整个公式的计算结果
                                </div>
                            </div>
                        </div>
                        <div class="form-group">
                            <label class="form-label">连接状态</label>
                            <div style="font-size: 11px; color: #666;">
                                ${getNodeConnectionStatus(nodeData.id)}
                            </div>
                        </div>
                    `;
                    break;
            }
            
            propertiesHTML += `
                </div>
                <div class="property-section">
                    <div class="section-title">🔗 连接信息</div>
                    <div style="font-size: 12px; color: #666;">
                        <div>输入端口数: ${config.inputs}</div>
                        <div>输出端口数: ${config.outputs}</div>
                    </div>
                </div>
            `;
            
            propertyContent.innerHTML = propertiesHTML;
        }

        // 获取节点连接状态
        function getNodeConnectionStatus(nodeId) {
            const inputConnections = Array.from(connections.values())
                .filter(conn => conn.to.nodeId === nodeId);
                
            if (inputConnections.length > 0) {
                return `✅ 已连接 ${inputConnections.length} 个输入`;
            } else {
                return `⚠️ 未连接输入，无法产生结果`;
            }
        }

        // 显示默认属性面板
        function showDefaultProperties() {
            const propertyContent = document.getElementById('propertyContent');
            propertyContent.innerHTML = `
                <div style="text-align: center; padding: 40px 20px; color: #999;">
                    <div style="font-size: 36px; margin-bottom: 16px;">🎛️</div>
                    <div>请选择一个节点进行配置</div>
                    <div style="font-size: 12px; margin-top: 12px;">
                        你可以点击画布中的任意节点来查看和编辑其属性
                    </div>
                </div>
            `;
        }

        // 更新节点属性
        function updateNodeProperty(nodeId, property, value) {
            const nodeData = nodes.get(nodeId);
            if (nodeData) {
                nodeData.properties[property] = value;
                
                // 如果是操作符变化，更新节点显示
                if (property === 'operator' && (nodeData.type === 'condition')) {
                    updateNodeDisplayText(nodeData);
                }
            }
        }

        // 更新节点显示文本
        function updateNodeDisplayText(nodeData) {
            const contentDiv = nodeData.element.querySelector('.node-content select');
            if (contentDiv && nodeData.type === 'condition') {
                // 不需要更新，因为选择框本身就会显示选中的中文选项
            }
        }

        // 删除节点
        function deleteNode(nodeId) {
            const nodeData = nodes.get(nodeId);
            if (nodeData) {
                // 删除相关连接
                const connectionsToDelete = [];
                connections.forEach((connection, connectionId) => {
                    if (connection.from.nodeId === nodeId || connection.to.nodeId === nodeId) {
                        connectionsToDelete.push(connectionId);
                    }
                });
                
                connectionsToDelete.forEach(connectionId => {
                    connections.delete(connectionId);
                });
                
                // 删除节点元素
                nodeData.element.remove();
                nodes.delete(nodeId);
                
                // 如果是选中的节点，取消选择
                if (selectedNode === nodeId) {
                    selectNode(null);
                }
                
                // 更新连接线
                updateConnections();
                
                // 如果没有节点了，显示提示
                if (nodes.size === 0) {
                    document.getElementById('dropHint').style.display = 'block';
                    // 清空预览
                    const preview = document.getElementById('formulaPreview');
                    preview.innerHTML = '<p style="color: #999; text-align: center;">请先在画布上设计公式，然后点击"生成表达式"按钮...</p>';
                }
            }
        }

        // 开始连接
        function startConnection(event, nodeId, portType, portIndex) {
            event.stopPropagation();
            
            if (!isConnecting) {
                isConnecting = true;
                connectionStart = { nodeId, portType, portIndex };
            } else {
                // 完成连接
                const connectionEnd = { nodeId, portType, portIndex };
                
                // 验证连接是否有效（输出连接到输入）
                if (connectionStart.portType !== connectionEnd.portType) {
                    const from = connectionStart.portType === 'output' ? connectionStart : connectionEnd;
                    const to = connectionStart.portType === 'input' ? connectionStart : connectionEnd;
                    
                    createConnection(from, to);
                }
                
                isConnecting = false;
                connectionStart = null;
            }
        }

        // 创建连接
        function createConnection(from, to) {
            const connectionId = `${from.nodeId}_${from.portIndex}_${to.nodeId}_${to.portIndex}`;
            
            // 检查连接是否已存在
            if (connections.has(connectionId)) {
                return;
            }
            
            // 禁止节点连接到自己
            if (from.nodeId === to.nodeId) {
                showSelfConnectionError();
                return;
            }
            
            // 验证端口类型兼容性
            if (!validatePortTypes(from, to)) {
                showTypeError(from, to);
                return;
            }
            
            // 检查目标输入端口是否已经有连接，如果有则删除旧连接
            const existingConnections = Array.from(connections.entries());
            const conflictingConnections = existingConnections.filter(([id, conn]) => 
                conn.to.nodeId === to.nodeId && conn.to.portIndex === to.portIndex
            );
            
            if (conflictingConnections.length > 0) {
                conflictingConnections.forEach(([id, conn]) => {
                    connections.delete(id);
                });
            }
            
            // 存储连接数据
            connections.set(connectionId, { from, to });
            
            // 更新连接线显示
            updateConnections();
        }

        // 验证端口类型兼容性
        function validatePortTypes(from, to) {
            const fromNode = nodes.get(from.nodeId);
            const toNode = nodes.get(to.nodeId);
            
            if (!fromNode || !toNode) return false;
            
            // 获取输出端口类型
            const outputType = getPortType(fromNode, 'output', from.portIndex);
            // 获取输入端口类型  
            const inputType = getPortType(toNode, 'input', to.portIndex);
            
            // 验证类型兼容性
            return isTypeCompatible(outputType, inputType);
        }

        // 获取端口数据类型
        function getPortType(nodeData, portType, portIndex) {
            const config = nodeData.config;
            
            if (portType === 'output') {
                if (nodeData.type === 'input') {
                    // 参数节点根据参数类型返回
                    return nodeData.subtype; // 'number', 'string', 'boolean'
                }
                return config.outputTypes ? config.outputTypes[0] : 'any';
            } else {
                // input端口
                if (config.inputTypes) {
                    if (config.inputTypes.length === 1) {
                        // 所有输入端口同类型
                        return config.inputTypes[0];
                    } else {
                        // 不同端口不同类型
                        return config.inputTypes[portIndex] || 'any';
                    }
                }
                
                return 'any';
            }
        }

        // 检查类型兼容性
        function isTypeCompatible(outputType, inputType) {
            // any类型接受所有输入，any输出连接到任何输入
            if (inputType === 'any') return true;
            if (outputType === 'any') return true;
            
            // 相同类型完全兼容
            if (outputType === inputType) return true;
            
            // 严格类型检查：不允许不匹配的连接
            return false;
        }

        // 显示类型错误提示
        function showTypeError(from, to) {
            const fromNode = nodes.get(from.nodeId);
            const toNode = nodes.get(to.nodeId);
            
            const outputType = getPortType(fromNode, 'output', from.portIndex);
            const inputType = getPortType(toNode, 'input', to.portIndex);
            
            const typeDisplayMap = {
                'number': '🔢数字',
                'string': '📝文本', 
                'boolean': '☑️布尔',
                'any': '🔄任意'
            };
            
            const outputDisplay = typeDisplayMap[outputType] || outputType;
            const inputDisplay = typeDisplayMap[inputType] || inputType;
            
            const tooltip = document.getElementById('portTooltip');
            if (tooltip) {
                let message = `❌ 类型不匹配！\n${outputDisplay} 不能连接到 ${inputDisplay}`;
                
                // 添加具体的解决建议
                if (inputType === 'boolean') {
                    message += '\n\n💡 需要布尔值？尝试连接:\n• 比较运算结果 (>, <, ==)\n• 逻辑运算结果 (并且, 或者)\n• 布尔参数';
                } else if (inputType === 'number') {
                    message += '\n\n💡 需要数字？尝试连接:\n• 数字参数\n• 数学运算结果\n• 函数运算结果';
                }
                
                tooltip.innerHTML = message.replace(/\n/g, '<br>');
                tooltip.style.left = '50%';
                tooltip.style.top = '50%';
                tooltip.style.transform = 'translate(-50%, -50%)';
                tooltip.style.whiteSpace = 'normal';
                tooltip.style.maxWidth = '250px';
                tooltip.classList.add('show');
                
                // 5秒后自动隐藏
                setTimeout(() => {
                    hidePortTooltip();
                }, 5000);
            }
        }

        // 显示自连接错误提示
        function showSelfConnectionError() {
            const tooltip = document.getElementById('portTooltip');
            if (tooltip) {
                let message = `❌ 连接错误！\n节点不能连接到自己`;
                message += '\n\n💡 提示:\n• 节点的输出端口不能连接到自己的输入端口\n• 请连接到其他节点';
                
                tooltip.innerHTML = message.replace(/\n/g, '<br>');
                tooltip.style.left = '50%';
                tooltip.style.top = '50%';
                tooltip.style.transform = 'translate(-50%, -50%)';
                tooltip.style.whiteSpace = 'normal';
                tooltip.style.maxWidth = '250px';
                tooltip.classList.add('show');
                
                // 3秒后自动隐藏
                setTimeout(() => {
                    hidePortTooltip();
                }, 3000);
            }
        }

        // 更新连接线显示
        function updateConnections() {
            // 清空现有连接线
            connectionSvg.innerHTML = '';
            
            connections.forEach((connection, connectionId) => {
                const fromNode = nodes.get(connection.from.nodeId);
                const toNode = nodes.get(connection.to.nodeId);
                
                if (fromNode && toNode) {
                    // 获取精确的端口位置
                    const fromPortPos = getPortPosition(fromNode, 'output', connection.from.portIndex);
                    const toPortPos = getPortPosition(toNode, 'input', connection.to.portIndex);
                    
                    if (!fromPortPos || !toPortPos) {
                        console.warn('端口位置获取失败:', connection);
                        return; // 如果无法获取端口位置，跳过
                    }
                    
                    const x1 = fromPortPos.x;
                    const y1 = fromPortPos.y;
                    const x2 = toPortPos.x;
                    const y2 = toPortPos.y;
                    
                    // 检查坐标是否有效
                    if (isNaN(x1) || isNaN(y1) || isNaN(x2) || isNaN(y2)) {
                        console.warn('坐标无效:', {x1, y1, x2, y2});
                        return;
                    }
                    
                    // 创建贝塞尔曲线路径
                    const path = document.createElementNS('http://www.w3.org/2000/svg', 'path');
                    
                    // 统一的垂直连接贝塞尔曲线
                    const dy = Math.abs(y2 - y1) / 3;
                    const controlOffset = Math.max(30, dy); // 确保控制点有足够的偏移
                    
                    let d = `M ${x1} ${y1} C ${x1} ${y1 + controlOffset} ${x2} ${y2 - controlOffset} ${x2} ${y2}`;
                    
                    path.setAttribute('d', d);
                    path.setAttribute('class', 'connection-path');
                    path.setAttribute('data-connection-id', connectionId);
                    
                    // 添加点击删除功能
                    path.addEventListener('click', function(e) {
                        e.stopPropagation();
                        if (confirm('确定要删除这条连接线吗？')) {
                            connections.delete(connectionId);
                            updateConnections();
                        }
                    });
                    
                    connectionSvg.appendChild(path);
                    
                    // 在连接线中点添加删除按钮
                    const midX = (x1 + x2) / 2;
                    const midY = (y1 + y2) / 2;
                    
                    // 创建删除按钮组
                    const deleteBtn = document.createElementNS('http://www.w3.org/2000/svg', 'g');
                    deleteBtn.setAttribute('class', 'connection-delete-btn');
                    deleteBtn.setAttribute('data-connection-id', connectionId);
                    deleteBtn.setAttribute('transform', `translate(${midX}, ${midY})`);
                    
                    // 创建圆形背景
                    const circle = document.createElementNS('http://www.w3.org/2000/svg', 'circle');
                    circle.setAttribute('r', '10');
                    circle.setAttribute('cx', '0');
                    circle.setAttribute('cy', '0');
                    
                    // 创建×文字
                    const text = document.createElementNS('http://www.w3.org/2000/svg', 'text');
                    text.setAttribute('x', '0');
                    text.setAttribute('y', '0');
                    text.setAttribute('text-anchor', 'middle');
                    text.setAttribute('dominant-baseline', 'central');
                    text.textContent = '×';
                    
                    deleteBtn.appendChild(circle);
                    deleteBtn.appendChild(text);
                    
                    // 添加删除按钮的点击事件
                    deleteBtn.addEventListener('click', function(e) {
                        e.stopPropagation();
                        connections.delete(connectionId);
                        updateConnections();
                    });
                    
                    // 添加悬停效果
                    deleteBtn.addEventListener('mouseenter', function() {
                        path.style.stroke = '#ff4757';
                        path.style.strokeWidth = '3';
                    });
                    
                    deleteBtn.addEventListener('mouseleave', function() {
                        path.style.stroke = '#4facfe';
                        path.style.strokeWidth = '2';
                    });
                    
                    connectionSvg.appendChild(deleteBtn);
                }
            });
        }
        
        // 获取端口的精确位置（相对于SVG坐标系统）
        function getPortPosition(nodeData, portType, portIndex) {
            // 直接从DOM获取端口元素的实际渲染位置
            const portSelector = `.node-port[data-node-id="${nodeData.id}"][data-port-type="${portType}"][data-port-index="${portIndex}"]`;
            const portElement = document.querySelector(portSelector);
            
            if (portElement) {
                const portRect = portElement.getBoundingClientRect();
                const svgRect = connectionSvg.getBoundingClientRect();
                
                // 计算端口中心相对于SVG左上角的位置
                // getBoundingClientRect返回的是屏幕坐标，已经包含了所有变换（缩放、滚动等）
                const centerX = portRect.left - svgRect.left + portRect.width / 2;
                const centerY = portRect.top - svgRect.top + portRect.height / 2;
                
                return {
                    x: centerX,
                    y: centerY
                };
            }
            
            // 回退方案：无法找到端口元素时返回null
            return null;
        }

        // 更新画布大小
        function updateCanvasSize() {
            const canvasContainer = document.querySelector('.canvas-container');
            const canvas = document.getElementById('canvas');
            
            // SVG需要覆盖整个可滚动区域（包括隐藏部分）
            // 考虑缩放因子，SVG需要更大的尺寸
            const baseWidth = Math.max(canvasContainer.clientWidth, canvasContainer.scrollWidth, 2000);
            const baseHeight = Math.max(canvasContainer.clientHeight, canvasContainer.scrollHeight, 2000);
            
            // 放大时SVG需要更大的尺寸来覆盖所有内容
            // 使用一个更大的倍数确保超大缩放时也能显示
            const width = baseWidth * Math.max(1.5, currentZoomScale * 1.2);
            const height = baseHeight * Math.max(1.5, currentZoomScale * 1.2);
            
            connectionSvg.setAttribute('width', width);
            connectionSvg.setAttribute('height', height);
        }

        // 生成公式表达式
        function generateFormulaExpression() {
            // 找到输出节点
            const outputNodes = Array.from(nodes.values()).filter(node => node.type === 'output');
            
            if (outputNodes.length === 0) {
                return "// 请添加输出节点";
            }
            
            const expressions = [];
            
            outputNodes.forEach(outputNode => {
                const expression = buildExpressionFromNode(outputNode.id);
                if (expression) {
                    expressions.push(`result = ${expression}`);  // 固定使用 'result' 作为结果名
                }
            });
            
            return expressions.length > 0 ? expressions.join('\n') : "// 请连接节点构建表达式";
        }

        // 从节点构建表达式
        function buildExpressionFromNode(nodeId, visited = new Set()) {
            if (visited.has(nodeId)) {
                return `[循环引用: ${nodeId}]`;
            }
            visited.add(nodeId);
            
            const nodeData = nodes.get(nodeId);
            if (!nodeData) return '[节点不存在]';
            
            // 获取输入连接
            const inputConnections = Array.from(connections.values())
                .filter(conn => conn.to.nodeId === nodeId)
                .sort((a, b) => a.to.portIndex - b.to.portIndex);
            
            const inputs = inputConnections.map(conn => 
                buildExpressionFromNode(conn.from.nodeId, new Set(visited))
            );
            
            switch(nodeData.type) {
                case 'input':
                    const paramName = nodeData.properties.paramName;
                    if (paramName) {
                        return paramName;
                    } else {
                        return '[请选择参数]';
                    }
                
                case 'constant':
                    const constantValue = nodeData.properties.value;
                    if (nodeData.subtype === 'string') {
                        // 字符串常量需要添加单引号
                        return `'${constantValue || ''}'`;
                    } else if (nodeData.subtype === 'number') {
                        return constantValue || '0';
                    } else if (nodeData.subtype === 'boolean') {
                        return constantValue || 'true';
                    }
                    return '[常量值未设置]';
                    
                case 'math':
                    const operator = nodeData.properties.operator || nodeData.config.operator;
                    if (inputs.length >= 2) {
                        if (nodeData.config.expandable && inputs.length > 2) {
                            // 支持多个输入的运算 (如: a + b + c + d)
                            return `(${inputs.join(` ${operator} `)})`;
                        } else {
                            // 标准两个输入的运算
                            return `(${inputs[0]} ${operator} ${inputs[1]})`;
                        }
                    } else {
                        return `[${operator} 需要至少2个输入]`;
                    }
                    
                case 'function':
                    const funcName = nodeData.config.func;
                    // max 和 min 不需要 math. 前缀，其他函数都需要
                    const needsMathPrefix = !['max', 'min'].includes(funcName);
                    const fullFuncName = needsMathPrefix ? `math.${funcName}` : funcName;
                    
                    if (inputs.length > 0) {
                        // round 函数特殊处理：支持保留小数位数
                        if (funcName === 'round') {
                            const decimalPlaces = nodeData.properties.decimalPlaces || 0;
                            if (decimalPlaces > 0) {
                                // 保留n位小数：round(x * 10^n) / 10^n
                                const multiplier = Math.pow(10, decimalPlaces);
                                return `(math.round(${inputs[0]} * ${multiplier}) / ${multiplier}.0)`;
                            } else {
                                // 保留0位小数（整数）
                                return `math.round(${inputs[0]})`;
                            }
                        } else {
                            return `${fullFuncName}(${inputs.join(', ')})`;
                        }
                    } else {
                        return `${fullFuncName}([需要输入])`;
                    }
                    
                case 'condition':
                    if (nodeData.subtype === 'gt' || nodeData.subtype === 'lt' || 
                        nodeData.subtype === 'gte' || nodeData.subtype === 'lte' || 
                        nodeData.subtype === 'eq' || nodeData.subtype === 'neq') {
                        // 独立的比较运算节点
                        const operator = nodeData.properties.operator || nodeData.config.operator;
                        if (inputs.length >= 2) {
                            return `(${inputs[0]} ${operator} ${inputs[1]})`;
                        } else {
                            return `[比较运算 需要2个输入]`;
                        }
                    } else if (nodeData.subtype === 'and' || nodeData.subtype === 'or') {
                        // 独立的逻辑与/或运算节点
                        const operator = nodeData.properties.operator || nodeData.config.operator;
                        if (inputs.length >= 2) {
                            return `(${inputs[0]} ${operator} ${inputs[1]})`;
                        } else {
                            return `[逻辑运算 需要2个输入]`;
                        }
                    } else if (nodeData.subtype === 'not') {
                        // 独立的逻辑非运算节点
                        if (inputs.length >= 1) {
                            return `!(${inputs[0]})`;
                        } else {
                            return `[逻辑非 需要1个输入]`;
                        }
                    } else if (nodeData.subtype === 'simple') {
                        if (inputs.length >= 3) {
                            return `(${inputs[0]} ? ${inputs[1]} : ${inputs[2]})`;
                        } else {
                            return `[三目运算 需要3个输入: 条件, 真值, 假值]`;
                        }
                    } else if (nodeData.subtype === 'controller') {
                        // 条件控制器：组合所有分支的结果
                        return buildConditionControllerExpression(nodeData, inputs);
                    }
                    break;
                    
                case 'branch':
                    if (nodeData.subtype === 'if') {
                        if (inputs.length >= 2) {
                            return `if (${inputs[0]}) { (${inputs[1]}) }`;
                        } else {
                            return `[if分支 需要2个输入: 条件, 值]`;
                        }
                    } else if (nodeData.subtype === 'elsif') {
                        if (inputs.length >= 2) {
                            return `elsif (${inputs[0]}) { (${inputs[1]}) }`;
                        } else {
                            return `[elsif分支 需要2个输入: 条件, 值]`;
                        }
                    } else if (nodeData.subtype === 'else') {
                        if (inputs.length >= 1) {
                            return `else { (${inputs[0]}) }`;
                        } else {
                            return `[else分支 需要1个输入: 值]`;
                        }
                    }
                    break;
                    
                case 'output':
                    if (inputs.length > 0) {
                        return inputs[0];
                    } else {
                        return '[输出节点需要输入]';
                    }
                    
                default:
                    return '[未知节点类型]';
            }
        }

        // 构建条件控制器表达式
        function buildConditionControllerExpression(nodeData, inputs) {
            if (inputs.length === 0) {
                return '[条件控制器需要连接分支]';
            }
            
            // 按类型分类和排序分支表达式
            const ifBranches = [];
            const elsifBranches = [];
            const elseBranches = [];
            
            inputs.forEach(branchExpr => {
                if (branchExpr.startsWith('if ')) {
                    ifBranches.push(branchExpr);
                } else if (branchExpr.startsWith('elsif ')) {
                    elsifBranches.push(branchExpr);
                } else if (branchExpr.startsWith('else ')) {
                    elseBranches.push(branchExpr);
                }
            });
            
            // 按正确顺序组合：if + elsif + else
            let combinedExpression = '';
            
            // 添加if分支（应该只有一个）
            if (ifBranches.length > 0) {
                combinedExpression = ifBranches[0];
            } else {
                return '[缺少if分支]';
            }
            
            // 添加elsif分支（可能有多个）
            elsifBranches.forEach(elsifExpr => {
                combinedExpression += ` ${elsifExpr}`;
            });
            
            // 添加else分支（应该只有一个）
            if (elseBranches.length > 0) {
                combinedExpression += ` ${elseBranches[0]}`;
            }
            
            return combinedExpression || '[请连接if-elsif-else分支]';
        }

        // 更新公式预览 (仅在手动调用时使用)
        function updateFormulaPreview() {
            const preview = document.getElementById('formulaPreview');
            
            if (nodes.size === 0) {
                preview.innerHTML = '<p style="color: #999; text-align: center;">请先在画布上设计公式...</p>';
                return;
            }
            
            const expression = generateFormulaExpression();
            let cleanExpression = expression;
            
            // 安全地移除 "result = " 前缀
            if (cleanExpression.startsWith('result = ')) {
                cleanExpression = cleanExpression.substring(9);
            }
            
            // 简化显示格式
            preview.innerHTML = `
                <h3 class="formula-display">
                    <span class="formula-label">📐 公式：</span>${cleanExpression}
                </h3>
            `;
        }

        // 工具栏功能
        function clearCanvas() {
            if (confirm('确定要清空所有节点吗？')) {
                nodes.forEach(node => node.element.remove());
                nodes.clear();
                connections.clear();
                connectionSvg.innerHTML = '';
                selectNode(null);
                document.getElementById('dropHint').style.display = 'block';
                
                // 重置当前公式名称和页面标题
                currentFormulaName = null;
                document.title = '公式设计器 - 可视化拖拽设计';
                
                // 重置预览内容
                const preview = document.getElementById('formulaPreview');
                preview.innerHTML = '<p style="color: #999; text-align: center;">请先在画布上设计公式，然后点击"生成表达式"按钮...</p>';
                
                // 重置参数为默认值
                globalParameters.clear();
                initializeParameters();
                
                // 清空公式信息输入框
                clearFormulaInfo();
                
                // 重置缩放
                resetZoom();
            }
        }

        function autoLayout() {
            // 从上到下的层级布局
            const layers = [];
            const visited = new Set();
            const nodeDepths = new Map();
            
            // 计算每个节点的层级深度
            function calculateDepth(nodeId, depth = 0) {
                if (visited.has(nodeId)) return nodeDepths.get(nodeId) || depth;
                
                visited.add(nodeId);
                const nodeData = nodes.get(nodeId);
                if (!nodeData) return depth;
                
                // 查找所有输入到此节点的连接
                const inputConnections = Array.from(connections.values())
                    .filter(conn => conn.to.nodeId === nodeId);
                
                let maxInputDepth = -1;
                inputConnections.forEach(conn => {
                    const inputDepth = calculateDepth(conn.from.nodeId, depth);
                    maxInputDepth = Math.max(maxInputDepth, inputDepth);
                });
                
                const currentDepth = maxInputDepth + 1;
                nodeDepths.set(nodeId, currentDepth);
                
                if (!layers[currentDepth]) layers[currentDepth] = [];
                layers[currentDepth].push(nodeData);
                
                return currentDepth;
            }
            
            // 为所有节点计算深度
            nodes.forEach((nodeData, nodeId) => {
                if (!visited.has(nodeId)) {
                    calculateDepth(nodeId);
                }
            });
            
            // 如果没有连接，按节点类型分层
            if (layers.length === 0 || layers.every(layer => !layer || layer.length === 0)) {
                const typeOrder = ['input', 'math', 'function', 'condition', 'branch', 'output'];
                const typeGroups = {};
                
                nodes.forEach(nodeData => {
                    const type = nodeData.type;
                    if (!typeGroups[type]) typeGroups[type] = [];
                    typeGroups[type].push(nodeData);
                });
                
                let layerIndex = 0;
                typeOrder.forEach(type => {
                    if (typeGroups[type] && typeGroups[type].length > 0) {
                        layers[layerIndex] = typeGroups[type];
                        layerIndex++;
                    }
                });
            }
            
            // 布局参数
            const layerHeight = 150; // 层与层之间的垂直间距
            const startY = 50; // 起始Y位置
            const nodeSpacing = 140; // 节点间水平间距
            const canvasWidth = 1200; // 画布宽度
            
            // 为每一层布局节点
            layers.forEach((layer, layerIndex) => {
                if (!layer || layer.length === 0) return;
                
                const layerY = startY + (layerIndex * layerHeight);
                
                // 分离普通节点和控制器组
                const regularNodes = [];
                const controllerGroups = new Map();
                
                layer.forEach(nodeData => {
                    if (nodeData.type === 'condition' && nodeData.subtype === 'controller') {
                        // 收集控制器及其分支
                        const branches = nodeData.properties.branches || [];
                        const branchNodes = branches.map(id => nodes.get(id)).filter(n => n);
                        controllerGroups.set(nodeData, branchNodes);
                    } else if (nodeData.type !== 'branch') {
                        // 只添加非分支的普通节点（分支节点由控制器管理）
                        regularNodes.push(nodeData);
                    }
                });
                
                // 优化节点位置以减少交叉
                optimizeNodePositions(regularNodes, layerIndex);
                
                // 计算总宽度需求
                const controllerGroupCount = controllerGroups.size;
                const regularNodeCount = regularNodes.length; 
                const totalGroups = controllerGroupCount + regularNodeCount;
                
                if (totalGroups === 0) return;
                
                // 计算起始X位置，使整层居中，但确保至少有50px的左边距
                const totalWidth = (totalGroups - 1) * nodeSpacing;
                const centeredX = (canvasWidth - totalWidth) / 2;
                const minMargin = 50; // 最小左边距
                const startX = Math.max(minMargin, centeredX);
                
                let currentX = startX;
                
                // 布局普通节点（使用优化后的顺序）
                regularNodes.forEach(nodeData => {
                    nodeData.element.style.left = currentX + 'px';
                    nodeData.element.style.top = layerY + 'px';
                    nodeData.x = currentX;
                    nodeData.y = layerY;
                    
                    currentX += nodeSpacing;
                });
                
                // 布局控制器组
                controllerGroups.forEach((branchNodes, controllerData) => {
                // 控制器位置
                    const controllerX = currentX;
                    const controllerY = layerY;
                
                controllerData.element.style.left = controllerX + 'px';
                controllerData.element.style.top = controllerY + 'px';
                controllerData.x = controllerX;
                controllerData.y = controllerY;
                
                    // 分支节点排列在控制器上方
                    const branchY = controllerY - 100;
                    const branchSpacing = Math.min(120, 200 / Math.max(branchNodes.length, 1));
                    const branchStartX = controllerX - ((branchNodes.length - 1) * branchSpacing) / 2;
                    
                    // 按类型排序分支：if -> elsif -> else
                    const sortOrder = {'if': 0, 'elsif': 1, 'else': 2};
                    branchNodes.sort((a, b) => {
                        const orderA = sortOrder[a.subtype] || 3;
                        const orderB = sortOrder[b.subtype] || 3;
                        return orderA - orderB;
                    });
                    
                    branchNodes.forEach((branchData, index) => {
                    const branchX = branchStartX + (index * branchSpacing);
                    
                    branchData.element.style.left = branchX + 'px';
                    branchData.element.style.top = branchY + 'px';
                    branchData.x = branchX;
                    branchData.y = branchY;
                });
                
                    currentX += nodeSpacing;
                });
            });
            
            // 优化节点位置以减少连接线交叉
            function optimizeNodePositions(layerNodes, layerIndex) {
                if (layerNodes.length <= 1) return;
                
                // 计算每个节点的连接重心
                const nodeWeights = layerNodes.map(nodeData => {
                    let totalX = 0;
                    let connectionCount = 0;
                    
                    // 计算输入连接的重心
                    const inputConnections = Array.from(connections.values())
                        .filter(conn => conn.to.nodeId === nodeData.id);
                    
                    inputConnections.forEach(conn => {
                        const fromNode = nodes.get(conn.from.nodeId);
                        if (fromNode) {
                            totalX += fromNode.x || 0;
                            connectionCount++;
                        }
                    });
                    
                    // 计算输出连接的重心
                    const outputConnections = Array.from(connections.values())
                        .filter(conn => conn.from.nodeId === nodeData.id);
                    
                    outputConnections.forEach(conn => {
                        const toNode = nodes.get(conn.to.nodeId);
                        if (toNode) {
                            totalX += toNode.x || 0;
                            connectionCount++;
                        }
                    });
                    
                    return {
                        node: nodeData,
                        weight: connectionCount > 0 ? totalX / connectionCount : 0,
                        connectionCount: connectionCount
                    };
                });
                
                // 按连接重心排序，优先考虑连接数多的节点
                nodeWeights.sort((a, b) => {
                    // 如果连接重心差距很大，按重心排序
                    const weightDiff = Math.abs(a.weight - b.weight);
                    if (weightDiff > 100) {
                        return a.weight - b.weight;
                    }
                    // 否则按连接数排序（连接多的节点优先）
                    return b.connectionCount - a.connectionCount;
                });
                
                // 更新节点顺序
                layerNodes.length = 0;
                nodeWeights.forEach(item => layerNodes.push(item.node));
                
                // 进一步优化：局部交换减少交叉（简单高效的启发式算法）
                if (layerNodes.length > 2) {
                    localSwapOptimization(layerNodes);
                }
            }
            
            // 局部交换优化：通过交换相邻节点减少交叉
            function localSwapOptimization(layerNodes) {
                let improved = true;
                let iterations = 0;
                const maxIterations = 3; // 限制迭代次数，确保性能
                
                while (improved && iterations < maxIterations) {
                    improved = false;
                    iterations++;
                    
                    for (let i = 0; i < layerNodes.length - 1; i++) {
                        const node1 = layerNodes[i];
                        const node2 = layerNodes[i + 1];
                        
                        // 简单的交叉评估：比较交换前后的连接线"拉伸程度"
                        const originalCost = calculateNodeConnectionCost(node1, i * 140) + 
                                           calculateNodeConnectionCost(node2, (i + 1) * 140);
                        
                        const swappedCost = calculateNodeConnectionCost(node1, (i + 1) * 140) + 
                                          calculateNodeConnectionCost(node2, i * 140);
                        
                        // 如果交换后成本更低，就交换
                        if (swappedCost < originalCost * 0.95) { // 5%的改进阈值，避免微小改动
                            [layerNodes[i], layerNodes[i + 1]] = [layerNodes[i + 1], layerNodes[i]];
                            improved = true;
                        }
                    }
                }
            }
            
            // 计算节点在指定X位置的连接成本（连接线的总"拉伸"距离）
            function calculateNodeConnectionCost(nodeData, proposedX) {
                let totalCost = 0;
                
                // 输入连接成本
                const inputConnections = Array.from(connections.values())
                    .filter(conn => conn.to.nodeId === nodeData.id);
                
                inputConnections.forEach(conn => {
                    const fromNode = nodes.get(conn.from.nodeId);
                    if (fromNode && fromNode.x !== undefined) {
                        totalCost += Math.abs(fromNode.x - proposedX);
                    }
                });
                
                // 输出连接成本
                const outputConnections = Array.from(connections.values())
                    .filter(conn => conn.from.nodeId === nodeData.id);
                
                outputConnections.forEach(conn => {
                    const toNode = nodes.get(conn.to.nodeId);
                    if (toNode && toNode.x !== undefined) {
                        totalCost += Math.abs(toNode.x - proposedX);
                    }
                });
                
                return totalCost;
            }
            
            // 延迟更新连接线，确保DOM更新完成
            setTimeout(() => {
                updateCanvasSize();
                updateConnections();
                
                setTimeout(() => {
                    updateConnections();
                    // 自动布局后重置缩放以便查看完整布局
                    if (currentZoomScale !== 1) {
                        resetZoom();
                    }
                }, 50);
            }, 150);
        }

        // 按连接端口顺序排列分支，避免交叉
        function sortBranchesByConnection(controllerId, branches) {
            // 获取控制器的所有输入连接
            const controllerConnections = Array.from(connections.values())
                .filter(conn => conn.to.nodeId === controllerId)
                .sort((a, b) => a.to.portIndex - b.to.portIndex);
            
            // 按连接端口顺序创建分支数组
            const sortedBranches = [];
            
            controllerConnections.forEach(connection => {
                const branchData = branches.find(b => b.id === connection.from.nodeId);
                if (branchData) {
                    sortedBranches.push(branchData);
                }
            });
            
            // 添加未连接的分支（按类型排序）
            const unconnectedBranches = branches.filter(b => !sortedBranches.includes(b));
            const sortOrder = {'if': 0, 'elsif': 1, 'else': 2};
            unconnectedBranches.sort((a, b) => {
                const orderA = sortOrder[a.subtype] || 3;
                const orderB = sortOrder[b.subtype] || 3;
                return orderA - orderB;
            });
            
            return [...sortedBranches, ...unconnectedBranches];
        }

        let currentZoomScale = 1;

        function zoomIn() {
            currentZoomScale = Math.min(currentZoomScale * 1.2, 3);
            applyZoom();
        }

        function zoomOut() {
            currentZoomScale = Math.max(currentZoomScale / 1.2, 0.3);
            applyZoom();
        }

        function resetZoom() {
            currentZoomScale = 1;
            applyZoom();
        }

        function applyZoom() {
            canvas.style.transform = `scale(${currentZoomScale})`;
            
            // 调整画布的实际尺寸以支持滚动
            const baseWidth = 100;
            const baseHeight = 100;
            canvas.style.width = `${baseWidth * currentZoomScale}%`;
            canvas.style.height = `${baseHeight * currentZoomScale}%`;
            
            // 更新缩放比例显示
            const zoomLevelElement = document.getElementById('zoomLevel');
            if (zoomLevelElement) {
                zoomLevelElement.textContent = Math.round(currentZoomScale * 100) + '%';
            }
            
            // 移除了CSS transition，transform会立即生效
            // 使用requestAnimationFrame + setTimeout组合确保准确性
            requestAnimationFrame(() => {
                requestAnimationFrame(() => {
                    updateCanvasSize();
                    setTimeout(() => {
                        updateConnections();
                    }, 50);
                });
            });
        }

        // 生成表达式
        function generateExpression() {
            if (nodes.size === 0) {
                const preview = document.getElementById('formulaPreview');
                preview.innerHTML = '<p style="color: #ffc107; text-align: center; font-weight: 600;">⚠️ 画布为空，请先添加节点设计公式</p>';
                return;
            }
            
            // 检查是否有输出结果节点
            const outputNodes = Array.from(nodes.values()).filter(node => node.type === 'output');
            if (outputNodes.length === 0) {
                const preview = document.getElementById('formulaPreview');
                preview.innerHTML = '<p style="color: #ffc107; text-align: center; font-weight: 600;">⚠️ 请添加"输出结果"节点来完成公式设计</p>';
                return;
            }
            
            // 生成表达式
            const expression = generateFormulaExpression();
            let cleanExpression = expression;
            
            // 安全地移除 "result = " 前缀
            if (cleanExpression.startsWith('result = ')) {
                cleanExpression = cleanExpression.substring(9);
            }
            
            // 简化显示格式
            const preview = document.getElementById('formulaPreview');
            if (preview) {
                preview.innerHTML = `
                    <h3 class="formula-display">
                        <span class="formula-label">📐 公式：</span>${cleanExpression}
                    </h3>
                `;
            }
        }

        // 测试公式
        function testFormula() {
            const expression = generateFormulaExpression();
            
            if (!expression || expression.includes('[') || expression.includes('需要')) {
                return;
            }
            
            // 获取使用的参数，直接使用默认值
            const usedParamNames = new Set();
            const inputNodes = Array.from(nodes.values()).filter(node => node.type === 'input' && node.properties.paramName);
            inputNodes.forEach(node => {
                if (node.properties.paramName) {
                    usedParamNames.add(node.properties.paramName);
                }
            });
            
            const inputParams = {};
            
            usedParamNames.forEach(paramName => {
                const globalParam = Array.from(globalParameters.values()).find(p => p.name === paramName);
                if (globalParam) {
                    inputParams[paramName] = globalParam.defaultValue;
                }
            });
            
            // 调用API测试
            testFormulaWithAPI(expression, inputParams);
        }

        // 使用API测试公式
        async function testFormulaWithAPI(expression, inputParams) {
            try {
                // 正确清理表达式：只移除 "result = " 前缀
                let cleanExpression = expression;
                
                // 如果表达式以 "result = " 开头，移除这部分
                if (cleanExpression.startsWith('result = ')) {
                    cleanExpression = cleanExpression.substring(9); // 移除 "result = "
                }
                
                // 移除可能的换行符和多余空格
                cleanExpression = cleanExpression.trim();
                
                const response = await fetch('http://localhost:9999/api/formula/calculate', {
                    method: 'POST',
                    headers: {
                        'Content-Type': 'application/json',
                    },
                    body: JSON.stringify({
                        expression: cleanExpression,
                        inputs: inputParams
                    })
                });
                
                const result = await response.json();
                
                // 在预览区域显示简化的结果
                const preview = document.getElementById('formulaPreview');
                const currentContent = preview.innerHTML;
                
                if (result.success && result.data && result.data.data) {
                    // 只显示最终的result值
                    const finalResult = result.data.data.result;
                    
                    // 检查是否已有公式显示
                    const formulaDiv = preview.querySelector('.formula-display');
                    
                    if (formulaDiv) {
                        // 如果有公式显示，添加结果
                        const existingResult = preview.querySelector('.result-display');
                        if (existingResult) {
                            existingResult.innerHTML = `<span class="result-label">🎯 结果：</span>${finalResult}`;
                        } else {
                            preview.innerHTML += `
                                <h4 class="result-display">
                                    <span class="result-label">🎯 结果：</span>${finalResult}
                                </h4>
                            `;
                        }
                    } else {
                        // 如果没有公式，只显示结果
                        preview.innerHTML = `
                            <h4 class="result-display">
                                <span class="result-label">🎯 结果：</span>${finalResult}
                            </h4>
                        `;
                    }
                } else {
                    // 错误情况
                    const formulaDiv = preview.querySelector('.formula-display');
                    
                    if (formulaDiv) {
                        const existingResult = preview.querySelector('.result-display');
                        if (existingResult) {
                            existingResult.innerHTML = `<span class="result-label">❌ 结果：</span>计算失败`;
                        } else {
                            preview.innerHTML += `
                                <h4 class="result-display" style="color: #dc3545;">
                                    <span class="result-label">❌ 结果：</span>计算失败 - ${result.message || '未知错误'}
                                </h4>
                            `;
                        }
                    } else {
                        preview.innerHTML = `
                            <h4 class="result-display" style="color: #dc3545;">
                                <span class="result-label">❌ 结果：</span>计算失败 - ${result.message || '未知错误'}
                            </h4>
                        `;
                    }
                }
                
            } catch (error) {
                const preview = document.getElementById('formulaPreview');
                const formulaDiv = preview.querySelector('.formula-display');
                
                if (formulaDiv) {
                    const existingResult = preview.querySelector('.result-display');
                    if (existingResult) {
                        existingResult.innerHTML = `<span class="result-label">❌ 结果：</span>网络错误`;
                        existingResult.style.color = '#dc3545';
                    } else {
                        preview.innerHTML += `
                            <h4 class="result-display" style="color: #dc3545;">
                                <span class="result-label">❌ 结果：</span>网络错误 - ${error.message}
                            </h4>
                        `;
                    }
                } else {
                    preview.innerHTML = `
                        <h4 class="result-display" style="color: #dc3545;">
                            <span class="result-label">❌ 结果：</span>网络错误 - ${error.message}
                        </h4>
                    `;
                }
            }
        }

        // 保存公式
        async function saveFormula() {
            if (nodes.size === 0) {
                alert('❌ 画布为空，无法保存公式');
                return;
            }

            // 检查是否有输出结果节点
            const outputNodes = Array.from(nodes.values()).filter(node => node.type === 'output');
            if (outputNodes.length === 0) {
                alert('❌ 请添加"输出结果"节点后再保存');
                return;
            }

            // 获取输入框中的公式信息
            const formulaInfo = getCurrentFormulaInfo();
            let formulaName = formulaInfo.name;
            let description = formulaInfo.description;
            
            // 如果名称为空，提示用户输入
            if (!formulaName) {
                formulaName = prompt('请输入公式名称:', '新建公式');
            if (!formulaName || formulaName.trim() === '') {
                    return;
                }
                formulaName = formulaName.trim();
                
                // 更新输入框中的名称
                const nameInput = document.getElementById('formulaNameInput');
                if (nameInput) {
                    nameInput.value = formulaName;
                }
            }
            
            // 如果是编辑现有公式且输入框中的描述为空，使用原有描述
            if (currentFormulaName && !description) {
                description = await getCurrentFormulaDescription(currentFormulaName);
            }
            
            // 如果描述仍为空且是新建公式，询问用户
            if (!description && !currentFormulaName) {
                description = prompt('请输入公式描述 (可选):', '') || '';
                
                // 更新输入框中的描述
                const descInput = document.getElementById('formulaDescInput');
                if (descInput) {
                    descInput.value = description;
                }
            }
            
            // 如果是更新现有公式，确认操作
            if (currentFormulaName && !confirm(`确定要更新公式 "${formulaName}" 吗？`)) {
                return;
            }

            try {
                // 收集当前公式数据
                const formulaData = {
                    name: formulaName,
                    description: description,
                    parameters: Object.fromEntries(globalParameters),
                    nodes: Array.from(nodes.values()).map(node => ({
                        id: node.id,
                        type: node.type,
                        subtype: node.subtype,
                        properties: node.properties,
                        x: node.x,
                        y: node.y,
                        dynamicInputs: node.dynamicInputs
                    })),
                    connections: Array.from(connections.entries()).map(([id, conn]) => ({
                        id: id,
                        from: conn.from,
                        to: conn.to
                    })),
                    expression: generateFormulaExpression().replace('result = ', ''),
                    createTime: currentFormulaName ? undefined : Date.now(), // 新建才设置创建时间
                    updateTime: Date.now()
                };

                const response = await fetch('http://localhost:9999/api/formula/save', {
                    method: 'POST',
                    headers: {
                        'Content-Type': 'application/json',
                    },
                    body: JSON.stringify(formulaData)
                });

                const result = await response.json();
                
                if (result.success) {
                    const isUpdate = currentFormulaName !== null;
                    const message = isUpdate ? `✅ 公式 "${formulaName}" 更新成功` : `✅ 公式 "${formulaName}" 保存成功`;
                    alert(message);
                    
                    // 更新当前公式名称和页面标题
                    currentFormulaName = formulaName;
                    document.title = `编辑公式: ${formulaName} - 公式设计器`;
                    
                    // 确保输入框显示最新的信息
                    const nameInput = document.getElementById('formulaNameInput');
                    const descInput = document.getElementById('formulaDescInput');
                    if (nameInput) nameInput.value = formulaName;
                    if (descInput) descInput.value = description;
                    
                } else {
                    alert(`❌ 保存失败: ${result.message}`);
                }

            } catch (error) {
                alert(`❌ 保存失败: ${error.message}`);
            }
        }

        // 更新公式信息
        function updateFormulaInfo() {
            // 当用户在输入框中输入信息时，这个函数会被调用
            // 主要用于实时更新页面标题
            const nameInput = document.getElementById('formulaNameInput');
            if (nameInput && nameInput.value.trim()) {
                document.title = `编辑公式: ${nameInput.value.trim()} - 公式设计器`;
                if (!currentFormulaName) {
                    // 只有在新建公式时才自动设置currentFormulaName
                    currentFormulaName = nameInput.value.trim();
                }
            } else if (nameInput && !nameInput.value.trim() && !currentFormulaName) {
                // 如果清空了输入框且不是编辑现有公式，重置标题
                document.title = '公式设计器 - 可视化拖拽设计';
            }
        }

        // 填充公式信息到输入框
        function fillFormulaInfo(formula) {
            const nameInput = document.getElementById('formulaNameInput');
            const descInput = document.getElementById('formulaDescInput');
            
            if (nameInput) {
                nameInput.value = formula.name || '';
            }
            if (descInput) {
                descInput.value = formula.description || '';
            }
        }

        // 清空公式信息输入框
        function clearFormulaInfo() {
            const nameInput = document.getElementById('formulaNameInput');
            const descInput = document.getElementById('formulaDescInput');
            
            if (nameInput) {
                nameInput.value = '';
            }
            if (descInput) {
                descInput.value = '';
            }
        }

        // 获取当前输入框中的公式信息
        function getCurrentFormulaInfo() {
            const nameInput = document.getElementById('formulaNameInput');
            const descInput = document.getElementById('formulaDescInput');
            
            return {
                name: nameInput ? nameInput.value.trim() : '',
                description: descInput ? descInput.value.trim() : ''
            };
        }

        // 获取当前公式的描述
        async function getCurrentFormulaDescription(formulaName) {
            try {
                const response = await fetch(`http://localhost:9999/api/formula/get/${encodeURIComponent(formulaName)}`);
                const result = await response.json();
                
                if (result.success && result.data) {
                    return result.data.description || '';
                }
            } catch (error) {
                console.error('获取公式描述失败:', error);
            }
            return '';
        }


         // 加载公式
         async function loadFormula(formula) {
             try {
                 // 清空当前画布
                 nodes.forEach(node => node.element.remove());
                 nodes.clear();
                 connections.clear();
                 connectionSvg.innerHTML = '';
                 globalParameters.clear();
 
                 // 填充公式信息到输入框
                 fillFormulaInfo(formula);
 
                 // 恢复参数
                 if (formula.parameters) {
                     Object.entries(formula.parameters).forEach(([id, param]) => {
                         globalParameters.set(id, param);
                     });
                     updateParameterDisplay();
                 }
 
                 // 恢复节点
                 if (formula.nodes) {
                     for (const nodeData of formula.nodes) {
                         await recreateNode(nodeData);
                     }
                     
                     // 修复：更新nodeIdCounter为比所有已有节点ID更大的值
                     let maxNodeId = 0;
                     formula.nodes.forEach(nodeData => {
                         // 从节点ID中提取数字部分，例如 "node_5" -> 5
                         const match = nodeData.id.match(/node_(\d+)/);
                         if (match) {
                             const nodeNum = parseInt(match[1]);
                             if (nodeNum > maxNodeId) {
                                 maxNodeId = nodeNum;
                             }
                         }
                     });
                     // 设置为最大ID + 1，确保新节点不会冲突
                     nodeIdCounter = maxNodeId + 1;
                 }
 
                 // 恢复连接
                 if (formula.connections) {
                     setTimeout(() => {
                         formula.connections.forEach(connData => {
                             connections.set(connData.id, {
                                 from: connData.from,
                                 to: connData.to
                             });
                         });
                         
                         // 重置缩放并更新连接
                         resetZoom();
                         
                         // 显示公式
                         const preview = document.getElementById('formulaPreview');
                         preview.innerHTML = `
                             <h3 class="formula-display">
                                 <span class="formula-label">📐 公式：</span>${formula.expression}
                             </h3>
                         `;
                     }, 500);
                 }
 
                 document.getElementById('dropHint').style.display = 'none';
 
             } catch (error) {
                 alert(`❌ 加载失败: ${error.message}`);
             }
         }

        // 重新创建节点
        async function recreateNode(nodeData) {
            return new Promise((resolve) => {
                if (nodeData.type === 'condition' && nodeData.subtype === 'controller') {
                    // 特殊处理条件控制器：不使用自动创建分支的逻辑
                    const config = nodeConfigs.condition.controller;
                    const nodeElement = document.createElement('div');
                    nodeElement.className = `canvas-node condition controller`;
                    nodeElement.id = nodeData.id;
                    nodeElement.style.left = nodeData.x + 'px';
                    nodeElement.style.top = nodeData.y + 'px';
                    
                    nodeElement.innerHTML = `
                        <div class="node-header">
                            <span class="node-title">${config.icon} ${config.name}</span>
                            <button class="node-close" onclick="deleteControllerGroup('${nodeData.id}')">×</button>
                        </div>
                        <div class="node-content">
                            <div style="text-align: center; font-size: 10px; color: #4facfe; font-weight: bold;">条件控制器</div>
                        </div>
                        ${createNodePorts(nodeData.dynamicInputs || config.inputs, config.outputs, nodeData.id, true, 'condition', 'controller')}
                    `;
                    
                    canvas.appendChild(nodeElement);
                } else if (nodeData.type === 'input') {
                    // 特殊处理输入参数节点，使用完整的参数信息显示
                    const config = nodeConfigs.input[nodeData.subtype];
                    const nodeElement = document.createElement('div');
                    nodeElement.className = `canvas-node input`;
                    nodeElement.id = nodeData.id;
                    nodeElement.style.left = nodeData.x + 'px';
                    nodeElement.style.top = nodeData.y + 'px';
                    
                    // 获取类型对应的图标
                    const typeIcons = {
                        'number': '🔢',
                        'string': '📝', 
                        'boolean': '☑️'
                    };
                    
                    const props = nodeData.properties || {};
                    const paramName = props.paramName || 'Unknown';
                    const paramType = props.type || nodeData.subtype;
                    const paramValue = props.defaultValue || '';
                    const paramDesc = props.description || paramName;
                    
                    nodeElement.innerHTML = `
                        <div class="node-header">
                            <span class="node-title">${typeIcons[paramType] || '🔢'} ${paramName}</span>
                            <button class="node-close" onclick="deleteNode('${nodeData.id}')">×</button>
                        </div>
                        <div class="node-content">
                            <div style="text-align: center; font-size: 11px; color: #007bff; background: white; padding: 8px 4px; border-radius: 2px;">${paramValue}</div>
                        </div>
                        ${createNodePorts(0, 1, nodeData.id, false, 'input', nodeData.subtype)}
                    `;
                    
                    canvas.appendChild(nodeElement);
                } else if (nodeData.type === 'constant') {
                    // 特殊处理常量节点，显示保存的值
                    const config = nodeConfigs.constant[nodeData.subtype];
                    const nodeElement = document.createElement('div');
                    nodeElement.className = `canvas-node constant`;
                    nodeElement.id = nodeData.id;
                    nodeElement.style.left = nodeData.x + 'px';
                    nodeElement.style.top = nodeData.y + 'px';
                    
                    const constantValue = nodeData.properties.value || '';
                    let contentHTML = '';
                    if (nodeData.subtype === 'number') {
                        contentHTML = `<input type="number" style="width: 100%; font-size: 14px; font-weight: 600; text-align: center;" value="${constantValue}" onchange="updateNodeProperty('${nodeData.id}', 'value', this.value)" placeholder="输入数字">`;
                    } else if (nodeData.subtype === 'string') {
                        contentHTML = `<input type="text" style="width: 100%; font-size: 14px; font-weight: 600; text-align: center;" value="${constantValue}" onchange="updateNodeProperty('${nodeData.id}', 'value', this.value)" placeholder="输入文本">`;
                    } else if (nodeData.subtype === 'boolean') {
                        contentHTML = `<select style="width: 100%; font-size: 14px; font-weight: 600;" onchange="updateNodeProperty('${nodeData.id}', 'value', this.value)">
                                        <option value="true" ${constantValue === 'true' ? 'selected' : ''}>true</option>
                                        <option value="false" ${constantValue === 'false' ? 'selected' : ''}>false</option>
                                    </select>`;
                    }
                    
                    nodeElement.innerHTML = `
                        <div class="node-header">
                            <span class="node-title">${config.icon} ${config.name}</span>
                            <button class="node-close" onclick="deleteNode('${nodeData.id}')">×</button>
                        </div>
                        <div class="node-content">
                            ${contentHTML}
                        </div>
                        ${createNodePorts(0, 1, nodeData.id, false, 'constant', nodeData.subtype)}
                    `;
                    
                    canvas.appendChild(nodeElement);
                } else {
                    // 普通节点恢复
                    const config = nodeConfigs[nodeData.type][nodeData.subtype];
                    const nodeElement = document.createElement('div');
                    
                    let className = `canvas-node ${nodeData.type}`;
                    if (nodeData.type === 'branch') {
                        className += ` ${nodeData.subtype}`;
                    }
                    nodeElement.className = className;
                    nodeElement.id = nodeData.id;
                    nodeElement.style.left = nodeData.x + 'px';
                    nodeElement.style.top = nodeData.y + 'px';
                    
                    nodeElement.innerHTML = `
                        <div class="node-header">
                            <span class="node-title">${config.icon} ${config.name}</span>
                            <button class="node-close" onclick="deleteNode('${nodeData.id}')">×</button>
                        </div>
                        <div class="node-content">
                            ${getNodeContentHTML(nodeData.type, nodeData.subtype, nodeData.id)}
                        </div>
                        ${createNodePorts(nodeData.dynamicInputs || config.inputs, config.outputs, nodeData.id, config.expandable, nodeData.type, nodeData.subtype)}
                    `;
                    
                    canvas.appendChild(nodeElement);
                }

                // 存储节点数据
                const newNodeData = {
                    id: nodeData.id,
                    type: nodeData.type,
                    subtype: nodeData.subtype,
                    config: nodeConfigs[nodeData.type][nodeData.subtype],
                    element: document.getElementById(nodeData.id),
                    properties: nodeData.properties,
                    x: nodeData.x,
                    y: nodeData.y,
                    dynamicInputs: nodeData.dynamicInputs
                };

                nodes.set(nodeData.id, newNodeData);
                addNodeEvents(newNodeData.element, newNodeData);
                
                resolve();
            });
        }

        // 初始化
        showDefaultProperties();